The Linux mv command is short for move, but it also handles the everyday rename work that keeps files and directories organized from the terminal. Use it to move paths into another directory, rename a file in place, or relocate whole project trees without leaving duplicate copies behind.
Most mv mistakes come from destination ambiguity: a missing directory becomes a rename, an existing file can be replaced, and a same-name directory will not merge when it already contains files. The useful patterns are overwrite protection, directory merge workarounds, batch moves, cross-filesystem metadata checks, and safer handoffs to rsync when verification matters.
Understand the Linux mv Command
The mv command works like dragging files between folders in a graphical file manager, but it stays scriptable and works over SSH connections where no GUI exists. When the source and destination share the same filesystem, mv performs an instant metadata rename without copying data. When they reside on different filesystems (for example, moving from /home to an external USB drive), mv falls back to copying the data first, then deleting the original after the copy succeeds.
The basic syntax follows this pattern:
mv [OPTIONS] SOURCE DESTINATION
- SOURCE: The file or directory you want to move or rename. Can be a relative path like
notes.txt, an absolute path like~/Downloads/report.pdf, or a glob pattern like*.log. - DESTINATION: Where the item ends up. If this is an existing directory, the source moves inside it. If it is a new filename, the source gets renamed. This distinction matters because
mv report.txt backupbehaves differently depending on whetherbackupis a directory or does not exist yet. - [OPTIONS]: Flags that modify behavior, such as
-ifor interactive confirmation,-nto skip existing files, or-vfor verbose output. Most quick moves need no options, but production scripts and shared directories benefit from safeguards.
By default, mv overwrites existing files at the destination without prompting. This makes it fast but dangerous in busy directories. Plan to add safeguards like -i or -n when moving into directories that might contain files with the same names.
mvcan replace destination files without asking. Use-i,-n, or a backup option when the target directory may already contain important files.
A simple example moves a single file into a directory:
mv notes.txt archive/
This moves notes.txt into archive/. If archive/ does not exist, mv interprets it as a filename and renames notes.txt to archive instead. Always verify the destination exists when you intend to move rather than rename. Use mkdir to create the target directory first if needed.
Quick Reference for mv Options
This quick reference summarizes common options. Options marked “GNU only” require GNU coreutils and are not available in BusyBox or other minimal implementations.
| Task | Options | GNU Only | What They Do |
|---|---|---|---|
| Move or rename | None | No | Relocates the source into DESTINATION if it is a directory, or renames it when you provide a filename. |
| Confirm before overwrite | -i | No | Prompts for confirmation before replacing an existing file. |
| Skip existing files | -n | No | Never overwrites; silently skips if the destination exists. |
| Force overwrite | -f | No | Overwrites without prompting, even if destination is write-protected. |
| Specify target directory | -t DIR | No | Move all sources into DIR. Useful with xargs pipelines. |
| Treat destination as file | -T | No | Forces mv to treat destination as a filename, not a directory. |
| Verbose output | -v | Yes | Prints each file as it moves. Useful for auditing batch operations. |
| Create backup before overwrite | -b, --backup | Yes | Saves a backup of the destination before replacing it. |
| Set backup suffix | --suffix=.bak | Yes | Changes the backup suffix from default ~ to a custom extension. |
| Update only if newer | -u | Yes | Moves only when source is newer than destination. Good for incremental syncs. |
| Restore SELinux context | -Z | Yes | Resets security context to the destination default on SELinux systems. |
| End option parsing | -- | No | Treats later names such as -report.txt as paths instead of options. |
Verify the mv Command Implementation
The mv command ships with core utilities on standard Linux distributions. Most systems use GNU coreutils, which provides the full option set shown above. Alpine Linux, BusyBox containers, and embedded systems may use BusyBox instead, which supports a smaller feature set.
Check whether mv is available:
command -v mv
/usr/bin/mv
If the command prints a path like /usr/bin/mv, you are ready. To identify which implementation you have, run:
mv --version
GNU coreutils displays version information. Relevant output begins with:
mv (GNU coreutils) 9.7
BusyBox shows an error because it does not support --version:
mv: unrecognized option '--version' BusyBox v1.37.0 () multi-call binary.
BusyBox mv Compatibility
BusyBox provides a minimal mv implementation suitable for containers and embedded systems. It supports only the core flags: -f, -i, -n, -t, and -T. Advanced features like backups (-b), update mode (-u), verbose output (-v), and SELinux context handling (-Z) are not available.
If you need GNU features on a BusyBox-based system, install coreutils:
apk add coreutils
After installation, /usr/bin/mv points to GNU coreutils, and mv --version confirms the switch.
Install GNU coreutils if mv Is Missing
On minimal container images or custom builds that lack coreutils, install it with your package manager. This is rarely needed on standard desktop or server installations.
Ubuntu and Debian:
sudo apt install coreutils
Fedora, RHEL, Rocky Linux, and AlmaLinux:
sudo dnf install coreutils
Arch Linux and Manjaro:
sudo pacman -S coreutils
openSUSE:
sudo zypper install coreutils
Gentoo:
sudo emerge sys-apps/coreutils
Void Linux:
sudo xbps-install -S coreutils
Practical Linux mv Command Examples
Start with ordinary file moves and renames before adding batch patterns or merge workarounds. A successful mv command is usually silent; add -v when you want the terminal to print each renamed path.
Example 1: Move a File to Another Directory
When you reorganize downloads or stash quick notes into long-term storage, point mv at the target directory.
mv document.txt ~/Documents/
This moves document.txt into your Documents directory. Verify the destination exists first; if it does not, mv treats the argument as a new filename and renames the file instead of moving it.
Example 2: Rename a File Without Moving It
Use this pattern to correct typos, bump version numbers, or prepare a file for automation that expects a specific name.
mv oldname.txt newname.txt
The file stays in the same directory with its new name. Add -i if there is a chance newname.txt already exists and you want a confirmation before replacing it.
Example 3: Move an Entire Directory
When archiving project folders or clearing temporary work trees, move the directory so every nested file travels with it.
mkdir -p ~/archive
mv projects/ ~/archive/
This command moves the projects/ directory and all its contents into ~/archive/. If ~/archive/projects already exists and is empty, GNU mv can replace it. If that directory is not empty, mv stops with a Directory not empty error instead of merging the contents.
Example 4: Move Multiple Files at Once
When several related files should travel together, list them before the destination. This is useful for grouping reports, logs, or configuration files that belong in the same archive directory.
mv report-q1.txt report-q2.txt ~/Documents/
Both reports land in ~/Documents/. Tab completion in the shell helps you add each filename accurately, and quoting protects names that contain spaces.
Example 5: Move Files by Extension
Shell globs let you sweep up related files, such as logs or screenshots, with a single command. This is particularly useful for cleaning up application logs, temporary files, or downloaded assets that need archiving.
mkdir -p ~/archive/logs
mv *.log ~/archive/logs/
The wildcard expands to every .log file in the current directory. Run ls *.log first to preview the list, and keep in mind that hidden files (those starting with a dot) require .*.log or an explicit path.
Move or Merge Directories with mv
mv can move a directory into another directory, but it does not merge two populated directories with the same name. If the destination already contains a non-empty directory named project, a move such as mv project archive/ fails instead of blending the contents.
When you only need to move the visible contents into an existing directory, target the contents rather than the parent directory:
mkdir -p archive/project
mv project/* archive/project/
The * glob does not match hidden files. For a safer directory merge that preserves existing destination files, handles hidden names, and keeps metadata, use rsync instead:
rsync -a --ignore-existing project/ archive/project/
Review the destination before deleting the original directory. That extra check matters because a merge can skip or overwrite files depending on the options you choose.
Practical mv Command Takeaways
- Check the destination path before moving a file; if the directory is missing,
mvrenames the file instead. - Renaming is just a move with a new filename, so you can clean up typos or version numbers without changing directories.
- List specific files or use globs to batch moves, and preview the match with
lswhen you are unsure. - Quote or escape filenames that contain spaces or special characters so the shell passes them to
mvintact.
Advanced mv Command Techniques
mvbehaves differently depending on whether the source and destination share the same filesystem. On the same filesystem it performs a quick metadata rename, but across devices it runs a copy-then-delete sequence. That slower path can be interrupted, so treat it like any long copy: confirm the destination is reachable, keep backups until you verify the new copy, and check device IDs withstat -c "%n -> %d"if you are unsure. For critical moves across filesystems,rsyncwith checksum verification provides safer handling thanmvalone.
Advanced mv work is mostly about controlling risk: prompts for collisions, safe handling for odd filenames, metadata checks, and knowing when another tool is better suited to the job.
Example 6: Prevent Overwrites with Safeguards
Shared working directories and deployment targets often contain files you cannot afford to replace accidentally. By default, mv overwrites existing files at the destination without prompting, so add safeguards before running a move that might collide with existing data.
Overwrite options change existing files at the destination. Use
-ifor a prompt or-nto skip collisions when you are not completely sure what already exists.
Use these options when you need extra protection:
-i(interactive): Prompts before overwriting a file. The prompt appears when the destination file already exists.-n(no-clobber): Skips the move when the destination already exists.-b(backup, GNU only): Saves the current destination as a backup by appending~or a custom suffix set with--suffix.-u(update, GNU only): Moves the source only when it is newer than the destination copy, useful for rolling updates.-f(force): Replaces files without prompting. Reserve it for scripts where you have already validated inputs.
mv -i config.yml deploy/
If deploy/config.yml already exists, the prompt asks before replacing it:
mv: overwrite 'deploy/config.yml'?
Combine these safeguards with cautious path checks or dry-run planning so you only move the files you intend.
When a script must treat the destination strictly as a filename, add -T (--no-target-directory on GNU systems). This prevents the command from silently dropping the source inside an existing directory with the same name, which is useful in scripts that assemble build artifacts.
Example 7: Move Symbolic Links Without Breaking Them
Symbolic links act as lightweight pointers, so decide whether you want to move the link itself or the file it targets before running mv. This matters when reorganizing configuration files, application directories, or shared libraries that use symlinks.
- By default,
mvmoves the symbolic link itself, not the file it points to. The target stays where it is. - If you move the file referenced by a symbolic link, the link can break if the target no longer exists at its original location. Update or recreate the link afterward.
To move only the link, treat it like any other file. This example archives a symlink while leaving the target in place:
mkdir -p project-config archives
touch project-config/site.conf
ln -s project-config/site.conf site.conf
mv site.conf archives/
ls -l archives/site.conf
When you relocate the target instead, move the real file and recreate or refresh the link so it points to the new path:
mkdir -p releases/2025-01-20
mv releases/current/config.yml releases/2025-01-20/config.yml
ln -sfn ../2025-01-20/config.yml releases/current/config.yml
The options -L and -P belong to cp, not mv, so mv always moves the link itself unless you explicitly move the target file.
Example 8: Preserve SELinux Contexts After Moves
On systems that enforce SELinux policies (Fedora, RHEL, Rocky Linux, AlmaLinux), a plain mv preserves the file’s current security context. That can be correct when the new location uses the same label, but it can also leave a web file, database file, or service config with a label that no longer matches the destination path.
Use the -Z (--context) option only when you intentionally want to relabel the destination with the default or a specific context. Verify the result with ls -Z, and avoid the option on files that carry custom labels you need to keep.
Check labels before and after a move when a service depends on SELinux access:
ls -Z /var/www/html/index.html
sudo mv /var/www/html/index.html /srv/www/
ls -Z /srv/www/index.html
If a directory needs the default context in its new location, apply it during the move with -Z and confirm the label afterward:
sudo mv -Z app.conf /etc/nginx/conf.d/
ls -Z /etc/nginx/conf.d/app.conf
Example 9: Preserve Timestamps Across Filesystems with mv
When GNU mv has to cross filesystems, it copies the file and then removes the original after the copy succeeds. It preserves the file mode and modification time during that copy path, and ownership is preserved when permissions and the destination filesystem allow it. The inode and change time still change because the destination is a new file.
Check the metadata before and after a cross-filesystem move with stat:
stat -c '%n %a %y' quarterly-backup.tar.zst
mv quarterly-backup.tar.zst /mnt/archive/
stat -c '%n %a %y' /mnt/archive/quarterly-backup.tar.zst
The exact timestamp will differ on your system, but the permission mode and modification time should match between the two rows:
quarterly-backup.tar.zst 640 2020-01-02 03:04:05.000000000 +0800 /mnt/archive/quarterly-backup.tar.zst 640 2020-01-02 03:04:05.000000000 +0800
Example 10: Move Thousands of Files Reliably
Shell globs can hit the operating system’s argument length limit when directories hold tens of thousands of files, leading to errors like:
bash: /bin/mv: Argument list too long
This limit comes from the shell, not mv. Pipe the file list through find and xargs to move everything safely:
mkdir -p ~/archive/logs
find . -maxdepth 1 -name "*.log" -print0 | xargs -0 mv -t ~/archive/logs/ --
The -t (--target-directory) flag tells mv where to place each file that arrives from the pipeline. The -- (double hyphen) marks the end of mv options, protecting against filenames that start with hyphens being misinterpreted as flags when they arrive from xargs.
Add -maxdepth 1 to keep the move scoped to the current directory or drop it when you need to traverse subdirectories. The -print0 and -0 pairing keeps filenames intact even when they contain spaces, quotes, or newlines, because filenames are separated with a null character instead of whitespace.
Example 11: Move Large Files Safely Across Filesystems
When moving very large files such as backups, ISO images, or database dumps across filesystems, prefer tools that verify integrity before deleting the source. This prevents data loss if the transfer gets interrupted or the destination runs out of space mid-copy.
A conservative workflow copies the data first, verifies integrity, and only then removes the source:
rsync -av release.iso /mnt/archive/
Relevant output includes the file being copied:
sending incremental file list release.iso
cmp release.iso /mnt/archive/release.iso
rsync preserves timestamps and permissions, while cmp or sha256sum confirms the copy succeeded before you delete the original file. cmp prints nothing when both files match.
Delete the source only after the copy and verification succeed. Keep
rm -iinteractive unless you are working inside a tested script.
rm -i release.iso
If you want rsync to clean up automatically once it finishes writing the destination, use its remove-source option:
rsync --remove-source-files -av release.iso /mnt/archive/
This flag deletes the source only after rsync reports success, but you still need to monitor available space and network reliability during the copy.
Example 12: Move Files with Leading Hyphens
Filenames that start with a hyphen (for example, -report.txt) look like options to mv, which can cause confusing errors or unexpected behavior. Use the double hyphen to stop option parsing when you move them:
mv -- -report.txt archive/
Alternatively, prefix the name with ./ when the file lives in the current directory so mv sees an explicit path:
mv ./-report.txt archive/
Both methods ensure that mv treats -report.txt as a literal filename instead of an option.
Avoid Common mv Command Mistakes
These issues trip up both new and experienced users. Knowing them ahead of time prevents frustrating data loss and debugging sessions.
- Missing or misspelled destination: When the destination does not exist,
mvrenames the source instead of moving it. Runls -d ~/archive/logs/first to confirm the directory exists. - Silent overwrites: By default,
mvreplaces existing files without asking. Use-ifor confirmation prompts or-nto skip existing files entirely. - Moving a directory into itself: Commands like
mv project project/archive/fail with a confusing error. Always verify that the destination is outside the source tree. - Glob expansion limits: Moving thousands of files with
mv *.log /archive/can hit shell argument limits. Usefindwithxargsfor large batches. - Unquoted filenames with spaces:
mv My File.txt dest/tries to move two files namedMyandFile.txt. Always quote paths containing spaces:mv "My File.txt" dest/. - Breaking symbolic links: Moving the target of a symlink leaves a dangling pointer. Check links with
ls -lbefore moving, and update or recreate links afterward. - Cross-filesystem moves without verification: When source and destination are on different filesystems,
mvcopies then deletes. For critical data, usersync -avfollowed bycmpor checksum verification before removing the original. - Metadata assumptions: Moved files usually keep their permissions and ownership, but cross-filesystem copies, mount options, and unprivileged moves can affect what survives. Verify with
ls -lorstatafter moving important files.
Troubleshoot Common mv Errors
When mv fails, it usually produces a short error message that points to the cause. Match the message first, then use the diagnostic and verification commands to confirm the fix.
Argument List Too Long
bash: /usr/bin/mv: Argument list too long
Cause: Shell glob expansion exceeded the system’s argument limit (typically 128-256 KB combined). This happens when wildcards like *.log match thousands of files.
Fix: Pipe the file list through find and xargs instead of relying on glob expansion:
mkdir -p ~/archive/logs
find . -maxdepth 1 -name "*.log" -print0 | xargs -0 mv -t ~/archive/logs/ --
Verify: Check that the files arrived at the destination:
find ~/archive/logs -maxdepth 1 -name "*.log" -print | wc -l
Cannot Move to a Subdirectory of Itself
mv: cannot move 'project' to a subdirectory of itself, 'project/backup/project'
Cause: You attempted to move a directory into one of its own subdirectories, which would create an infinite loop.
Fix: Move to a location outside the source tree, or rename the source first:
mv project /tmp/project-archive
Verify: Confirm the source now lives outside the original tree:
ls -ld /tmp/project-archive
Permission Denied
mv: cannot move 'config.yaml' to '/etc/app/config.yaml': Permission denied
Cause: Either you lack write permission on the destination directory, or the destination file exists and is write-protected.
Diagnose: Check directory permissions and file ownership:
ls -ld /etc/app/
ls -l /etc/app/config.yaml
Fix: Use sudo if you have administrative rights, or adjust permissions:
sudo mv config.yaml /etc/app/
Verify: Confirm the file arrived and check its owner:
ls -l /etc/app/config.yaml
Directory Not Empty When Moving Directories
mv: cannot overwrite 'backup/project': Directory not empty
Cause: You tried to move a directory to a destination that already contains a non-empty directory with the same basename. Unlike files, mv cannot overwrite or merge populated directories.
Fix: Choose a new destination name when you want to keep both directories:
mv project backup/project-new
For merging directory contents while preserving existing destination files, rsync is safer than mv:
rsync -av --ignore-existing project/ backup/project/
Verify: Check the destination before removing or archiving the original source:
find backup/project -maxdepth 2 -type f -print
Unrecognized Option
mv: unrecognized option '--backup' BusyBox v1.37.0 () multi-call binary.
Cause: You are using BusyBox mv, which lacks GNU-specific options like --backup, -u, -v, and -Z.
Fix: Install GNU coreutils to get the full feature set:
apk add coreutils # Alpine
mv --version # Verify GNU coreutils is now active
No Such File or Directory
mv: cannot stat 'report.txt': No such file or directory
Cause: The source file does not exist, the path is misspelled, or you are in the wrong directory.
Diagnose: Verify your current directory and check for the file:
pwd
ls -la report*
Fix: Use tab completion to verify filenames, or provide an absolute path:
mv ~/Downloads/report.txt ~/Documents/
mv Command Resources
The official GNU coreutils manual provides comprehensive documentation for all mv options and behaviors:
- GNU mv Manual – Complete reference for all options, including advanced features like
--exchange(atomic swap of two files),--no-copy(fail rather than copy across filesystems), and the extended--update=WHENsyntax for fine-grained control over which files to replace. - Backup Options – Details on backup suffixes, numbered backups, and the
VERSION_CONTROLenvironment variable.
Conclusion
The Linux mv command is ready for daily file moves, renames, guarded overwrites, and directory cleanup from the terminal. Keep -i or -n close when destination names may collide, use -- for filenames that look like options, and switch to rsync when a directory merge or cross-filesystem transfer needs verification before the source disappears.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>