292

I want to move content of a directory within another directory with the same folders.

Here's an example:

I have ./backup which has the directories base and test. Now, I want to move these directories to ./backupArchives.

I use this:

mv ./backup/* ./backupArchives

but I got the error

mv: cannot move './backup/base' to './backupsArchive/base': Directory not empty

I tried using --force, but no luck. Is there a way to move it when folders already exists?

Note: I just want to merge contents, there's no overwriting.

rex
  • 3
  • 3
UdK
  • 2,923
  • Are you just trying to merge the folders' contents into the destination, or are you trying to overwrite what's in the destination. (it also helps if you have the ENTIRE error, without using ...... to truncate data) – Thomas Ward Mar 19 '13 at 04:13
  • 1
    I just want to merge the contents, there's no overwriting. – UdK Mar 19 '13 at 04:20
  • 2
    @UdK Even if this would work, note that this would not merge the contents of the two directories. Moving a directory will replace its target. Have a look at rsync instead, it will do the merging. – zwets Mar 19 '13 at 07:38
  • Related: https://unix.stackexchange.com/questions/127712/merging-folders-with-mv – kelvin Sep 03 '19 at 19:08
  • I got into the same situation, i was doing mv <folder_name> ~/ from the downloads directory and was getting the error as: mv: cannot move '<folder_name>/' to '/home/user/<folder_name>': Directory not empty but when i did mv <folder_name> ~/home/, it worked, Didn't understand what solved the problem here though. – y_159 Sep 27 '21 at 15:22
  • @y_159 I suspect you moved the directory either to or into a new directory called "home" inside your home directory, and it probably wasn't what you wanted to do. – Erhannis Jan 18 '22 at 02:57

8 Answers8

326

Though its man page doesn't document it, mv will refuse to rename a directory to another directory if the target directory contains files. This is a good thing in your case because you turn out to want to merge the content of the source into the target, which mv will not do.

Use rsync -a backup/ backupArchives/ instead. After that rm -rf backup/*.

Instead of using rsync, you also can do the classical

(cd backup && tar c .) | (cd backupArchives && tar xf -)

which earns you more geek points.

zwets
  • 12,354
  • 5
    nice things to know! Both are working great. Thank's! – UdK Mar 20 '13 at 17:54
  • 2
    should be noted this requires you have the size of the folder in free space. And will cause horrible problems if not. – Pogrindis Oct 02 '14 at 21:07
  • 5
    @Pogrindis Please explain what horrible problems will occur, and how they are different from any other attempt to write to a full disk? Indeed, since both operations keep the original directory intact, if the operation fails you simply rm -rf backupArchives without consequences, let alone 'horrible' ones. – zwets Oct 05 '14 at 09:15
  • 1
    Also, must be noted, that rsync solution uses copying, which can be much slower with large files than mv. – Ivan Balashov Dec 22 '14 at 12:39
  • how do i give bounty? this man needs 10 more the geek solution was the only one viable in my safe mode ;)! – Banned_User Dec 23 '14 at 18:05
  • 5
    you can use rsync's --remove-source-files option instead of removing the folder with "rm -rf backup/*" command. – eaykin Feb 24 '15 at 16:11
  • 6
    Thanks for naming the classical approach, very helpful if rsync is not available! Also works with sudo using sudo sh -c '(cd backup && tar c .) | (cd backupArchives && tar xf -)' – ArendE Jun 23 '15 at 23:11
  • 3
    @eaykin the option --remove-source-files only removes files from the source directory, not directories. – zwets Jul 17 '15 at 12:58
  • @Ivan "rsync solution uses copying, which can be much slower". The --link-dest option can be (ab)used in rsync to use hard-links instead of copies: https://unix.stackexchange.com/a/127713 (it did not work for my use case though). – kelvin Sep 03 '19 at 19:07
  • What is tar xf - doing (x extract and f file, but -)? – Timo Jan 25 '21 at 14:02
  • @ArendE do I need the sh -c? The cmd as zwets writes it does nothing for me. – Timo Jan 25 '21 at 15:08
  • Worthwhile mentioning what the -a flag does here: "The archive mode behaves like the recursive mode but keeps all file permissions, symbolic links, file ownership, etc." – Pigpocket Mar 22 '22 at 16:12
82

Quick and dirty, if you know what you are doing:

cp -r ./backup/* ./backupArchives && rm -R ./backup/*
Pabi
  • 7,401
  • 3
  • 40
  • 49
pattivacek
  • 1,087
  • 10
  • 14
11

After the directory you moving you need * (represents any text or number). For example:

mv /var/www/* /recovery/wwwrecovery/

thats all, if you moving files, than you move as:

mv /var/www/index.php /recovery/index.php

Another way is to pack that folder content by using tar:

tar -cvzpf backup.tar.gz /var/www 

Then move it lie any other file. Also I recommend this step because tar compresses it and make it smaller in size.

To extract the files to another folder use

tar -xvzpf /var/www/

If you need to copy to a location you don't own, make sure to prepend your command with the sudo command after whichever option you decide to use.

sudo tar -cvzpf backup.tar.gz /var/www/
Mark Paskal
  • 2,900
  • I'm using Ubuntu 12.10 and I got: mv: invalid option -- 'R' Try `mv --help' for more information.

    Indeed .tar is nice, but I need to know how to move my files for this situation. Thank's for your help

    – UdK Mar 19 '13 at 04:34
  • i using 12.04 desktop and server and in both works well. be carefull, if you didnt make space betwen folfer and -R. i also tryed without -R works in same way for me, try without -R, but be carefull with spelling: linux matters lower and uppercase letters!!! than if path is incorect movingin or movingfrom location. if you dont have that folder that you wana move to just put -C after it and it will create it. also try first: find -iname name of your folder and run this command from root, just to see if it exists in other place if you miss spelled something. give me exact command that you used – Dimitris Theodoridis Mar 19 '13 at 04:47
  • what thaaa..... put that filename in betwen ** – Dimitris Theodoridis Mar 19 '13 at 04:54
  • 2
    That -R surely shouldn't come after the first argument. Options (nearly) always precede the command arguments. Also, mv has no -R option, and finally, recursion is irrelevant to a mv. @DimitrisTheodoridis please test your answer first. – zwets Mar 19 '13 at 07:34
  • 1
    yes my bro you are right, i always have problems with my spelling, and allways i have problem with terminal for that or command not found or create new files and directories that i dont know, just for bas spelling... by the way i used cp command, than here wrote mv sory for that bro :D – Dimitris Theodoridis Mar 19 '13 at 17:23
  • hey sorry, i will modiffy my answer so look back on it i made big mistake as i writte to you about mv and worked with something else. take look again – Dimitris Theodoridis Mar 19 '13 at 23:42
  • Ss'x1xx s so ex sc1 x ex x ex xxxxx SD s x ez SD x'xzzz ZZZ zzzzzzzzzzzzzzzzzzzzzzzzzz0 – spioter Sep 16 '21 at 11:43
  • The mv solution doesn't work if there are subdirectories in common (would expand to ex. mv /var/www/include /recovery/wwwrecovery/, breaking if include folder is already present in the dest directory). It also might not work if there are hidden files (in bash you'd either need shopt -s dotglob or, assuming no hidden file has a single-character name, mv /var/www/* /var/www/.??* /recovery/wwwrecovery/ ). – DimeCadmium Jul 06 '22 at 05:42
5

I had to copy a very large directory with a lot of large files, so I created hardlinks to the original files in the target directory like this:

cp -al ./backup/* ./backupArchives

Then I deleted the originals, leaving only one hardlink to each file.

Since hardlinks are quite space efficient, you could even use hardlinks to copy the backupArchives and backup directories to a new trial location, and check that the file counts are as you expect, as a dummy run. This assumes that your filesystem supports hardlinks - ext4 does.

4

Sure rsync does work, but this might work as well for machine that does not support rsync (i.e in cpanel, which rsync is not installed by default).

What about using:

cd /path/to/backup/ && cp -R --parents ./* ../backupArchives

Then remove the backup directory if necessary

Note1: You need to cd to the backup directory before executing the cp -R --parents ...

Note2: Double check the backupArchives directory if you got the new files from backup.

1

Before asking the question, let's consider a simplified case.

Suppose in /home/admin we have two folders foo and bar which have the same subdirectory structure, but each contains different files in it. Now we want to merge them into one. When we do things like mv foo/* bar, the error mv: directory not empty occurs.

My solution is to give up command line tools and switch to a GUI file manager, for example, dolphin. When you rename foo to bar in dolphin, it gives you the option to write into the destination folder, and asks you whether to overwrite existing files, interactively. This avoids copy and delete, which in effect saves your time without a single line of code.

PS: I didn't test every file manager out there. But most of them should have this feature.

btwiuse
  • 349
0

When moving directory during a script execution, you need to consider non-existing or empty directories, and also force override and removal without confirmation:

# If old directory exists, and isn't empty
if [[ -d old_dir ]] && [[ -n `ls -A old_dir` ]] ; then

  # Make a new directory (skip if already exists)
  mkdir -p new_dir

  # Copy all files to the new directory (-afr : Keep attributes, Force overwrite, Recursive copy)
  cp -afr old_dir/* new_dir/

  # Remove old directory
  rm -rf old_dir
fi
Noam Manos
  • 309
  • 5
  • 8
0

I just had the same problem of merging 2 directory trees, and didn't want to rsync or cp because it would have taken too long. The content was over 2TB, and since the destination was on the same disk, mv did it in a few seconds.

So this is one way of doing it:

  • find files to move
  • create the destination directory if needed
  • move the file (overwriting the destination file if it already exists)
cd $your_source_dir # go to your source dir.
dest=".."  # moving files to the parent dir. Replace with your destination

find . -type f | while read f; do d=$(dirname "$f") file=$(basename "$f") mkdir -p "$dest/$d" mv -f "$f" "$dest/$d/" done

After that, the source directory still has all the empty folders. They can be removed with

find . -type d -empty -delete
mivk
  • 5,312