I have a ton of files and dirs in a subdirectory I want to move to the parent directory. There are already some files and dirs in the target directory which need to be overwritten. Files that are only present in the target should be left untouched. Can I force mvto do that? It (mv * ..) complains
mv: cannot move `xyz' to `../xyz': Directory not empty
What am I missing?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You will have to copy them to the destination and then delete the source, using the commands cp -r * .. followed by rm -rf *.
I don’t think you can “merge” directories using mv.
Method 2
rsync would probably be a better option here. It’s as simple as rsync -a subdir/ ./.
My test tree in filename:contents format:
./file1:root ./file2:root ./dir/file3:dir ./dir/file4:dir ./subdir/dir/file3:subdir ./subdir/file1:subdir
Running rsync:
$ rsync -a -v subdir/ ./ sending incremental file list ./ file1 dir/ dir/file3
Gives:
./file1:subdir ./file2:root ./dir/file3:subdir ./dir/file4:dir ./subdir/dir/file3:subdir ./subdir/file1:subdir
And then, to emulate mv, you probably want to remove the source directory:
$ rm -r subdir/
Giving:
./file1:subdir ./file2:parent ./dir/file3:subdir ./dir/file4:dir
If this is wrong, can you please provide a similar example (e.g. using my test tree from near the top of this answer) with the desired result?
Method 3
rsync can delete the source after copying with the --remove-source-files parameter.
From the rsync man page:
--remove-source-files sender removes synchronized files (non-dir)
Method 4
You can do this with cp and rm, but without copying the massive amount of data you are (presumably) trying to avoid transferring. @mattdm alluded to this in his comment, and an answer for another question has a more complete discussion about various options.
cp -rlf source destination rm -r source
Essentially, the -l option for the cp command creates hard links to files rather than copying their data to new files.
Method 5
Here’s a script that moves files from under /path/to/source/root to the corresponding path under /path/to/destination/root.
- If a directory exists in both the source and the destination, the contents are moved-and-merged recursively.
- If a file or directory exists in the source but not in the destination, it is moved.
- Any file or directory that already exists in the destination is left behind. (In particular merged directories are left behind in the source. This is not easy to fix.)
Beware, untested code.
export dest='/path/to/destination/root'
cd /path/to/source/root
find . -type d ( -exec sh -c '[ -d "$dest/$0" ]' {} ; -o
-exec sh -c 'mv "$0" "$dest/$0"' {} ; -prune )
-o -exec sh -c '
if ! [ -e "$dest/$0" ]; then
mv -f "$0" "$dest/$0";
fi
' {} ;
Method 6
This thread is out there for years and still ranks #1 on google so i wanted to add another method.
How i usually do this:
packing the subdir content into a tarball, moving the tarball up to the parent directory and then extract it with the default –overwrite behaviour. This does exactly what you’re looking for. Afterwards you can remove your subdir.
cd xyz tar -cvzpf tmp.tar.gz * mv tmp.tar.gz ../tmp.tar.gz cd .. tar -xvzpf tmp.tar.gz rm -rf xyz rm -f tmp.tar.gz
Method 7
If you have enough storage you can do it the following way:
mv -bfv directory_1/* directory_2/ # all duplicate source files/directories
# will have ~ appended to them
find -name "*~" -delete # will recursively find and delete all files
# with ~ on the end
Make sure there aren’t any important files with a ~ on the end of them, but if there are you can add --suffix=whateveryouwant instead of the default.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0