How To Move A File In Linux

How To Move A File In Linux

Reading time1 min
#Linux#Shell#CommandLine#mv#FileManagement#FileTransfer

Mastering the mv Command: Practical File Movement on Linux

Misusing mv risks silent data loss. Yet, executed with rigor, it accelerates workflow, enforces data hygiene, and becomes essential in both routine scripts and production CI pipelines.


Fundamentals

mv handles two primary tasks: transferring a file or directory to a new location, and/or renaming it. On ext4 (common in Ubuntu 20.04+), a same-filesystem move is an inode update—nearly instantaneous, zero-copy. But there are subtleties worth noting.

Basic usage:

mv [OPTIONS] SOURCE TARGET
  • SOURCE: file(s) or directory to move.
  • TARGET: destination directory or filename.

Quick example:
Move logs.txt to /var/archive/ (overwrites silently if same-named file exists):

mv logs.txt /var/archive/

Rename while moving:

mv logs.txt /var/archive/logs-2024-06-14.txt

Overwrite Protection

The default behavior—overwriting without prompting—has caused unnecessary late-night recoveries. mv -i prompts for confirmation:

mv -i *.conf /etc/myapp/
# mv: overwrite '/etc/myapp/app.conf'? y/n

For unattended scripts where "do not overwrite" is mandatory, prefer -n:

mv -n report.csv /mnt/backup/
# If /mnt/backup/report.csv exists, nothing is done—no prompt.

Gotcha: Both -i and -n together: -n takes precedence.


Visibility: Watching What Happens

mv -v (verbose) displays every operation:

mv -v *.log /tmp/logs/
# 'error.log' -> '/tmp/logs/error.log'
# 'access.log' -> '/tmp/logs/access.log'

This is indispensable in troubleshooting automation, or where logs are required for auditing.


Moving Multiple Items

Wildcards (*, ?) expand files—subject to shell glob rules:

mv *.tar.gz /srv/tarballs/

Or explicitly list:

mv image1.png image2.png assets/

Bulk moves in scripts should always check for existence or permissions (see next section).


Moving Directories

mv works recursively for directories by default. But, unexpectedly, issues arise across filesystems:

mv data/ /mnt/export/

Running strace on this command across filesystems (use df . to verify) reveals mv does a copy+delete; it’s not atomic and is interrupted by a sudden SIGKILL (see partial directories—ls shows moved files, some linger in source).

For large datasets, consider rsync with --remove-source-files and proper verification.


Cross-Device Moves

Expect the following difference:

  • Same device: inode move, fast, atomic.
  • Between / and /mnt/usb/: actual file copy occurs.

Manual alternative (showing “interleaving” danger):

cp --preserve=all bigfile.img /mnt/usb/
# Only after verifying size/checksum:
rm bigfile.img

Note: Ejecting storage before completion leaves partial files and no warning. For critical data, hash with sha256sum before removing the original.


Scripting and Automation

Automated file archival is a standard pattern in centralized logging and retention management.

Example: Archive .log files older than 30 days:

#!/bin/bash
find /var/log/myapp/ -type f -name '*.log' -mtime +30 -exec mv -v {} /var/log/myapp/archive/ \;
  • -mtime +30: Files last modified >30 days ago.
  • -exec mv -v {}: Atomically moves in a loop; possible race if file is removed mid-process.

Known Issue: With high file churn, there's a window where find returns a file that disappears by move-time (mv: cannot stat ...).
Wrap in if [ -e "$file" ]; then mv ...; fi for more robust error handling.


Advanced Insight

Permissions

Moving files requires write permissions on the source’s parent (so inode can be unlinked) and on the target directory. When scripts fail silently, usually it’s a permissions issue:

mv /data/secure/db.sqlite /backup/
# mv: cannot move 'db.sqlite' to '/backup/db.sqlite': Permission denied

Testing With echo

For destructive batch moves, echo the command first:

find . -name '*.bak' -mtime +14 -exec echo mv {} /mnt/backups/old/ \;

Scrutinize output, then run without echo.

File Patterns and Hidden Files

By default, mv * target/ does not match dotfiles (files beginning with .). Use shopt -s dotglob in Bash if hidden files must be included.


Quick Reference Table

ScenarioCommand Example
Move single filemv report.md /srv/archive/
Rename while movingmv test.sh /scripts/test-2024-06.sh
Move multiple filesmv *.dat rawdata/
Prompt before overwritemv -i server.cfg /etc/app/
Never overwritemv -n data.json /backup/
Verbose (track every move)mv -v img1.png img2.png media/
Move directorymv old_data/ processed/
Move across filesystems (manual)cp --preserve=all large.mkv /mnt/usb/ && rm large.mkv

Underrated Tactics

  • Use mv --backup=numbered (mv -n --backup=numbered file dest/) for automatic versioning if moved file already exists.
  • Consider locking mechanisms (flock) in concurrent scripts to avoid race conditions.
  • Incorporate set -euo pipefail atop shell scripts for robust error management during batch moves.

In summary:
mv is deceptively simple, yet unforgiving—a single misstep can erase data without a trace. Test with non-critical files, log every move when automating, and be hyper-aware of filesystem boundaries and permissions. Sometimes, for non-atomic moves or high-load environments, rsync or a transactional copy/delete is the safer trade-off.


Note: For further detail, consult man mv (coreutils >=8.30), or observe modifications via inotifywait for real-time move tracking during scripting/debugging.