506

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?

MackM
  • 2,906
  • 5
  • 31
  • 45
mnowotka
  • 16,430
  • 18
  • 88
  • 134
  • 2
    https://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 Answers8

779

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
Neal
  • 4,468
  • 36
  • 33
hovanessyan
  • 30,580
  • 6
  • 55
  • 83
  • 56
    Note, 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
  • @AaronFranke looks like it does. – Boris Verkhovskiy Aug 26 '19 at 06:07
  • 3
    Even 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
137

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.

ndemou
  • 4,691
  • 2
  • 30
  • 33
Hans Ginzel
  • 8,192
  • 3
  • 24
  • 22
  • 10
    You want to add the `--ignore-existing` flag to prevent existing files from being overwritten. – Uyghur Lives Matter Aug 16 '14 at 18:22
  • 8
    Complete command `rsync -a -v --ignore-existing ` is indeed the correct answer, instead of `cp -u`above. – Whitebird May 18 '15 at 09:04
  • 1
    If 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
    some servers just has no rsync – mebada Apr 04 '19 at 10:59
  • 2
    absolutely. 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
63
cp -n

Is what you want. See the man page.

bucko
  • 1,148
  • 6
  • 5
  • 1
    The 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
39

This will work on RedHat:

false | cp -i source destination 2>/dev/null

Updating and not overwriting is something different.

ceving
  • 21,900
  • 13
  • 104
  • 178
37

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.

Grim...
  • 16,518
  • 7
  • 45
  • 61
17

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.

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
9

Some version of cp do not have the --no-clobber option. In that case:

  echo n | cp -vipr src/* dst
Shōgun8
  • 482
  • 10
  • 20
-3

This works for me yes n | cp -i src dest

CipherXEN
  • 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