I want to cp a directory but I do not want to overwrite any existing files even it they are older than the copied files. And I want to do it completely noninteractive as this will be a part of a Crontab Bash script. Any ideas?
- 
                    2https://unix.stackexchange.com/questions/67539/how-to-rsync-only-new-files – n611x007 Jun 26 '15 at 12:26
- 
                    1[SuperUser - Copy files in linux but avoid the copy if files do exist in destination](https://superuser.com/questions/118781/copy-files-in-linux-avoid-the-copy-if-files-do-exist-in-destination) – cssyphus Aug 13 '22 at 19:23
- 
                    **TL;DR:** For files, `cp -n copyFile pasteFile`, but for directories, `cp -r -n copyDir pasteDir` – Andrew Sep 25 '22 at 23:37
8 Answers
Taken from the man page:
-n, --no-clobber
              do not overwrite an existing file (overrides a previous -i option)
Example:
cp -n myoldfile.txt mycopiedfile.txt
 
    
    - 4,468
- 36
- 33
 
    
    - 30,580
- 6
- 55
- 83
- 
                    56Note, this will exit with an error if the file exists. To exit with success, try ```cp -n source.txt destination.txt || true``` – galenandrew Apr 01 '16 at 16:38
- 
                    25@galenandrew `cp -n` does not exit with error if the file exists on Ubuntu 12.04. – amit kumar Aug 29 '16 at 09:47
- 
                    @galenandrew Confirmed. Thank you. My project wasn't building in Xcode after adding a run script to my target. – Ruiz Apr 17 '17 at 20:30
- 
                    
- 
                    3Even with Ubuntu 18.04, the behavior is the same, that when the file exists, the command exit without erro, that is, an no op! This is dangerous! – Yu Shen Jul 21 '20 at 18:44
- 
                    `cp -n source.txt dest.txt || test -f dest.txt` won't ignore error if `source.txt` and `dest.txt` are missing – Jook Sep 24 '20 at 10:50
- 
                    FWIW, I have noticed that a *needed* `-n` exits `1` on Arch, but exits `0` on Manjaro. So, the behavior seems to be connected to the stack, similarly to how `cp -i` is often a link for `cp` in `.bashrc` on desktop distros. I only found this because I didn't stop at testing on my desktop, but on the actual machine it would be used—always test on your identical setup, not merely a distro related to the stack. – Jesse Apr 04 '23 at 09:31
- 
                    And, it would work for `cp -n myfolder/* newfolder/` with identical behavior, and will not break if encountering an existing file where the `-n` is needed. – Jesse Apr 04 '23 at 09:33
- 
                    always read your man page - that's the main takeaway from this answer at least IMO – hovanessyan Apr 04 '23 at 15:07
Consider using rsync.
rsync -a -v --ignore-existing src dst
As per comments rsync -a -v src dst is not correct because it will update existing files.
 
    
    - 4,691
- 2
- 30
- 33
 
    
    - 8,192
- 3
- 24
- 22
- 
                    10You want to add the `--ignore-existing` flag to prevent existing files from being overwritten. – Uyghur Lives Matter Aug 16 '14 at 18:22
- 
                    8Complete command `rsync -a -v --ignore-existing` is indeed the correct answer, instead of `cp -u`above. 
- 
                    1If a previous copy was interrupted and only a truncated file copied, I'm sure cp -u won't re-copy it... but will rsync, with --ignore-existing? Probably not either... so that makes them perfectly equivalent, right? – dagelf Dec 16 '17 at 16:40
- 
                    rsync keeps the file timestamp while cp uses the current time (in my experience) – Stefan Dec 27 '17 at 16:27
- 
                    You can use `--preserve=timestamps` with `cp` to preserve the timestamps. – Wilson F Aug 10 '18 at 22:33
- 
                    1
- 
                    2absolutely. I don't want to install `rsync` into my docker container, just to do a copy! I can't imagine why we should use a cannon when a BB gun will suffice. – Auspex Jun 04 '19 at 13:01
cp -n
Is what you want. See the man page.
 
    
    - 1,148
- 6
- 5
- 
                    1The man page: `-n Do not overwrite an existing file. (The -n option overrides any previous -f or -i options.)` – rebane2001 Dec 16 '21 at 13:00
This will work on RedHat:
false | cp -i source destination 2>/dev/null
Updating and not overwriting is something different.
 
    
    - 21,900
- 13
- 104
- 178
- 
                    6
- 
                    12
- 
                    1Obviously, this command won't work if you'll try to copy more than ARG_MAX files. To work-around this case, check this [link](http://unix.stackexchange.com/a/110285). – mginius Oct 27 '15 at 15:55
- 
                    12Also obviously, this command won't work if the earth crashes into the sun. – ceving Jan 27 '20 at 08:50
- 
                    @ceving I think you'll find that `oh-my-zsh` has an alias for that use-case. – Michael Paulukonis Nov 06 '20 at 16:45
For people that find that don't have an 'n' option (like me on RedHat) you can use cp -u to only write the file if the source is newer than the existing one (or there isn't an existing one).
[edit] As mentioned in the comments, this will overwrite older files, so isn't exactly what the OP wanted. Use ceving's answer for that.
 
    
    - 16,518
- 7
- 45
- 61
- 
                    14OP asked not to overwrite existing files **even if they are older than copied files**, so `-u` doesn't actually fit purpose. – Andrew Lott Feb 19 '14 at 10:39
- 
                    5Goodness, you're absolutely right. I'm surprised it took so long for anyone to notice. – Grim... Feb 19 '14 at 15:20
- 
                    It might not be what the OP asked for, but it's exactly what I needed for my Uberspace (Centos 7). Thanks! – Thomas Praxl Dec 11 '19 at 21:39
- 
                    2
Alpine linux: Below answer is only for case of single file: in alpine cp -n not working (and false | cp -i ... too) so solution working in my case that I found is:
if [ ! -f env.js ]; then cp env.example.js env.js; fi 
In above example if env.js file not exists then we copy env.example.js to env.js.
 
    
    - 85,173
- 29
- 368
- 345
Some version of cp do not have the --no-clobber option. In that case:
  echo n | cp -vipr src/* dst
 
    
    - 482
- 10
- 20
- 
                    Super good suggestion. I lost a lot of time debugging scripts until I realised the --no-clobber option is not available everywhere. Thanks! – Raz Aug 25 '20 at 03:54
- 
                    
This works for me yes n | cp -i src dest
 
    
    - 1
- 1
- 
                    It is much more effective to use the '--no-clobber' instead of forcing interactive copy with negative input. – dash-o Aug 27 '20 at 05:25
 
    