I'm trying to move the following move a large number of files that exist in the following structure to a /mnt/originals but I need to maintain the structure at the same time. I know cp would be a solution but can't use cp because of space limitations.


Etc. It is a pretty large set of files of different file names and types. I tried the following but it didn't work.

mv /mnt/originals-us/ /mnt/originals/ 

but get the following

mv: inter-device move failed: `/mnt/originals-us/10/0b9/' to `/mnt/originals/10/0b9'; unable to remove target: Is a directory

I also thought about writing a massively chanin-ed command but I don't think that would work either.

This is what I have so far.

find . -type f -print | rev | cut -d '/' -f1 | rev

This obviously gives me all the filenames but how do I chain it with the first part?


One option would be to use rsync with --remove-source-files

rsync -vr --remove-source-files /mnt/originals-us/ /mnt/originals/

Potential caveat: I do not know how rsync checks for space before performing potentially damaging actions. In a perfect world, rsync would calculate how much space is needed, check to see if that is available, then abort and warn the user or (if the space is adequate) perform the operation.

EDIT: I omitted the recursion option (-r) by mistake, thanks to the OP for mentioning, now fixed

| improve this answer | |
  • Worked perfectly after I added -r so it should be rsync -v -r --remove-source-files /mnt/originals-us/ /mnt/originals/ – Mark D Feb 21 '14 at 17:06
  • 2
    @MarkD I recommend -a (preserve everything), which includes -r as well as preservation of permissions, timestamps, special files, etc. – Gilles 'SO- stop being evil' Feb 21 '14 at 23:43

The rsync solution is a lot more efficient but it is possible with find, too. The worst case: one process per file:

find ... -exec cp --parents {} /dest/path \; -delete

find would delete the source file after successful copy only.

But we can start a project "fun with find" for optimization (remove the echos and the \ before the | after testing):

find ... -type d -exec echo mkdir /target/{} \; -exec bash -c \
  'echo find {} -maxdepth 1 -type f -print0 \| '\
  'xargs -0 mv --target-directory=/target/{}' \;

In the typical case: 5 processes per directory.

With your example (few files per directory) it may make sense to make a -print0 | xargs -0 mkdir in the target root first (and take the mkdir out of the main find call).

| improve this answer | |
  • I really like the solution but you're right rsync was more efficient. – Mark D Feb 21 '14 at 17:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.