Linux Move File To Another Directory

Linux Move File To Another Directory

Reading time1 min
#Linux#FileManagement#CommandLine#mv#rsync#ShellScripting

Linux: Moving Files Between Directories with Control and Metadata Preservation

Reorganizing data on production servers, sorting gigabytes of logs, or deploying release assets: on real Linux systems, moving files is rarely as trivial as mv src dest. The classic mv gets the job done on a single device, but specifics like permissions, ACLs, SELinux labels, and even cross-device boundaries quickly complicate matters.

Real-World Problem: Preventing Data Loss During File Relocation

Consider routine log rotation. A script that blindly moves /var/log/*.gz into an archive can silently overwrite existing files, drop extended attributes, or, if crossing filesystem boundaries (/var/mnt/backup), disrupt inode-level guarantees. In CI runners, you might inadvertently lose symlinks or misattribute ownership—root cause for subtle bugs months later.

Here’s how experienced engineers keep relocation operations predictable and safe.


The Limitations of Basic mv

mv /path/to/file.log /archive/directory/

Straightforward, but with constraints:

  • Overwrites target files without warning unless -i or -n is given.
  • No metadata preservation beyond default stat bits; extended attributes and SELinux contexts may be lost on some distributions (notably, on CentOS/RHEL 7.x with coreutils ≤8.22).
  • Inefficient across mountpoints: Moves between filesystems are implemented as copy+unlink, with visible performance impact and potential for partial state if interrupted.
  • No native filtering or batch control.

Example: Unintended Overwrite

mv latest_report.csv /archive/

No error if /archive/latest_report.csv exists—the old file is replaced without trace.


Interactive and Safe Moves: Avoiding Accidental Data Loss

Use -i for interactive mode:

mv -i report.csv /backup/

If the file exists, a prompt appears:

mv: overwrite '/backup/report.csv'? 

Alternatively, -n disables overwrites entirely—useful for unattended scripts.

FlagPurpose
-iPrompt before overwrite
-nNever overwrite existing files
-bCreate backups of overwritten

Preserving Metadata and Attributions: Using rsync for Moves

When the destination is a different filesystem, drop-in use of mv is inadequate if original timestamps, permissions, or ownership must be retained. Instead:

rsync -a --remove-source-files file1 /mnt/backup/
  • -a (archive): preserves permissions, times, ownership, links, devices, ACLs, xattrs.
  • --remove-source-files: deletes files from source after successful transfer.

Gotcha: Directories remain at the source—manually remove them post-transfer:

find /path/to/source -type d -empty -delete

In scripting, always validate transfer completion before cleanup to avoid data loss. NFS mounts, in particular, require explicit fsync on both ends for guarantees.


Selective and Conditional Moves: Beyond Basic Wildcards

Moving all .log files larger than 1M with safety prompt:

find /var/log -type f -name "*.log" -size +1M -exec mv -i {} /mnt/long-term-logs/ \;

To avoid false positives on filenames containing spaces or special characters, prefer null separation:

find /input -type f -print0 | xargs -0 mv -t /output/
  • xargs -0 and -print0 handle nonstandard characters and newlines robustly.
  • mv -t /output/ sets the target directory.

Test with dummy files containing spaces/hyphens:

touch "normal.log" "spaces and -weird.log"

This pattern is especially critical when batch-processing files from user uploads.


Handling Permissions and Ownership

User mismatch causes issues (mv fails with Permission denied). Use sudo where justified, but bear in mind file ownership post-move:

sudo mv /tmp/build-artifacts /opt/releases/
ls -ld /opt/releases/build-artifacts

If UID/GID differences matter (e.g., dockerized environments), prefer rsync plus explicit --chown if supported (rsync ≥3.1.0):

sudo rsync -a --chown=deploy:deploy --remove-source-files /tmp/build-artifacts/ /opt/releases/build-artifacts/
sudo rm -rf /tmp/build-artifacts/

Known issue: Filesystem-level ACLs may require an explicit setfacl step post-move.


Scripting Batch Operations: Practical Example

Batch-move .txt files interactively, robust to spaces/special characters:

#!/bin/bash
src="/data/incoming"
dst="/data/ready"
mkdir -p "$dst"

find "$src" -maxdepth 1 -type f -name "*.txt" -print0 |
  while IFS= read -r -d '' f; do
    mv -i -- "$f" "$dst"
  done
echo "Completed batch move at $(date)" >&2
  • -- signals end-of-options, preventing surprises if filenames start with -.
  • Logging to stderr avoids contaminating stdout (handy in pipelines).

Non-Obvious Tip: Moving Open Files and Inodes

On systems with long-running processes (databases, loggers), moving a file does not affect processes holding the original file descriptor; the old inode persists until released.

Check with:

lsof | grep deleted

If logrotate is used, rely on copy-truncate or post-move signaling.


Summary: Advanced Techniques for Predictable File Moves

  • Use -i, -n, or -b flags to prevent accidental overwrite.
  • Switch to rsync -a --remove-source-files for moves across filesystems or when metadata/ownership must be retained.
  • Leverage null-byte separation and -- for filenames with nonstandard characters.
  • Verify successful transfer before cleanup—especially with NFS or unreliable links.
  • Understand inode implications to avoid unexpected disk usage from moved-but-open files.
  • Review permissions, especially in automated or root-driven jobs.

Perfect is the enemy of done: sometimes a sweep with mv is enough, but for regulated environments or critical systems, always favor explicitness, backups, and dry runs.


Side note: On certain NAS appliances, both mv and rsync inherit quirks from vendor kernels—validate your approach before including in scheduled jobs.

Questions or edge-case scenarios? Review the coreutils and rsync man pages for options relevant to your distribution (--preserve-context, --xattrs, etc.). For security-centric filesystems, additional steps may be required.