Cao Yi

Merging Two Directories

Index

There’s a requirment from work today: merge two directories, all files, including directories should be reserved, if files in same name exist in the two directories, save one of them. In short, it uses one directory to override the other.

If we try the command mv, it will raises an error:

Git Bash (Windows):

$ mv demo3/* demo4/ -f
mv: cannot move 'demo3/demo' to 'demo4/demo': Directory not empty

Or

Bash Shell on RockyLinux:

$ mv demo3/* demo4 -f
mv: cannot move 'demo3/demo' to 'demo4/demo': File exists

As the above, it does not work even appending the --force (-f) parameter.

rsync

rsync -a --remove-source-files demo3/ demo4/ && rm demo3 -rf

After running rsync, demo3/ will be left empty, so it needs rm to remove demo3/.

mv command failed because mv doesn’t recursively merge non-empty directories by default—it treats them as simple moves and errors out when the target already exists and isn’t empty. rsync handles the recursion and overwriting seamlessly.

Python

rsync is wonderful, but it will remain some empty directories in demo3, let’s try Python script:

import shutil
import os

# Source and target directories
source_dir = 'demo3'
target_dir = 'demo4'

# Copy the entire directory tree, overwriting existing files/directories
shutil.copytree(source_dir, target_dir, dirs_exist_ok=True)

# Remove the source directory after successful copy (simulates move)
shutil.rmtree(source_dir)

It works perfectly as an improved version of mv.