Recursive, Non-Overwriting File Copy?

I've got a directory that contains a bunch of other folders containing CoffeeScript/ JavaScript files. I'm able to compile the CoffeeScript files into a new folder with the same folder structure fine.

What I want to do is copy all the *.js files in the source folder to the destination folder recursively. I also don't want to overwrite any files that are already present in the destination folder. Any thoughts of how to accomplish this?

I tried using cp -n source/**.js desination/ and cp -Rn source/**.js desination/ after looking at another similar question, but it doesn't seem to be working.

Any idea how to accomplish this?


Solution 1:

You could use rsync (it also does local copy)

rsync -r --ignore-existing --include=*/ --include=*.js --exclude=* source/ destination
  • -r to recurse into directories,
  • --ignore-existing to ignore existing files in destination,
  • the include and exclude filters mean: include all directories, include all *.js files, exclude the rest; the first include is needed, otherwise the final exclude will also exclude directories before their content is scanned.

Finally, you can add a -P if you want to watch progress, a --list-only if you want to see what it would copy without actually copying, and a -t if you want to preserve the timestamps.


This is not related, but I learned the rsync command recently, when I moved 15 years of documents from one partition to another. Confident that my files were there, I then wiped the old partition and put some other stuff in there; I realized later that I lost all the timestamps, and discovered the -t flag. Just wanted to share my distress :'(

Solution 2:

This is also achievable using cp. See here:

sudo cp -vnpr /xxx/* /yyy

xxx = source

yyy = destination

v = verbose

n = no clobber (no overwrite)

p = preserve permissions

r = recursive

Solution 3:

Looking at the man pages it seems that you want the -n option.

-n, --no-clobber
   do not overwrite an existing file (overrides the previous -i option)

Solution 4:

My distro didn't have clobber available, so:

echo n | cp -vipr xxx yyy

xxx = source

yyy = destination

v = verbose

i = interactive (prompt to overwrite) | which is why the command is preceded with "echo n |"

p = preserve permissions

r = recursive