92

I need to copy a /home/user folder from one hard disk to another one. It has 100,000 files and around 10G size.

I use

cp -r /origin /destination

sometimes I get some errors due to broken links, permissions and so on. So I fix the error, and need to start again the copy.

I wonder how could I tell the command "cp", once it tries to copy again, not to copy files again if they exist in the destination folder.

1
  • 4
    Don't us cp. Use rsync instead. Mar 11, 2010 at 16:08

9 Answers 9

62

cp -R -u -p /source /destination

The -u (or --update) flag does just this:

From the man page for cp:

-u, --update

copy only when the SOURCE file is newer than the destination file or when the destination file is missing

3
  • 13
    To literally only copy files that don't exist and not update existing ones, yes n | cp -i /source/* /destination 2>/dev/null
    – sventechie
    Nov 21, 2013 at 20:14
  • 5
    -u, --update copy only when the SOURCE file is newer than the destination file or when the destination file is missing -u, --update copy only when the SOURCE file is newer than the destination file or when the destination file is missing -p same as --preserve=mode,ownership,timestamps --preserve[=ATTR_LIST] preserve the specified attributes (default: mode,ownership,time‐ stamps), if possible additional attributes: context, links, xattr, all
    – Covich
    Feb 16, 2016 at 15:29
  • 2
    There is no -u option on my Mac. I think -n option can be used which means "Do not overwrite an existing file" according to the man page. I see that is in another answer. Troubling that different systems don't agree on something as fundamental as cp.
    – wcochran
    Feb 9, 2021 at 17:53
210

Just use cp -n <source> <dest>.

From man page:

-n, --no-clobber

do NOT overwrite an existing file (overrides a previous -i option)

4
  • 20
    This is the only true answer to the question.
    – sebix
    Mar 21, 2017 at 18:19
  • 1
    @sebix OP says "sometimes I get some errors [...] and need to start again the copy" Unless I'm mistaken, this solution wouldn't overwrite corrupt files at the destination by re-copying, so you could end up with a bunch of corrupt files at the destination, while thinking that the copy process has been successful.
    – joe
    Jul 28, 2020 at 17:37
  • 1
    @joe interesting remark, but the op explicitely asks for a way to skip copying files which already exist in the destination. I guess rsync would be a better choice, if one wants to validate the files integrity. (note that re-copying everything wouldn't help much, and could as well replace some valid files with corrupted ones.)
    – Balmipour
    Oct 14, 2020 at 14:20
  • @Balmipour Yep, rsync is a better approach here. "but the op explicitly asks [...]" It's quite clear from OP's post that they wouldn't want corrupt/half-copied files at the destination.
    – joe
    Oct 15, 2020 at 6:04
30

rsync -aq /src /dest

Apart from only copying newer files, it will even only copy the newer parts of files if the file has changed. It's intended for copying over network links where you want to minimise the amount of data - but it also works great locally.

1
  • If you are familiar with the interface of rsync then by all means use it, but the delta copy feature only happens when using it over a remote transport. When used on local paths it disables that feature because it would likely slow it down instead of speeding it up. It's also worth pointing out the default behavior of rsync is to replace an existing file if the modification time or size is different (whether newer or older). Mar 12 at 3:33
6

POSIX solution

Other answers use -u or -n options of cp. Neither of these is required by POSIX; nor is rsync from yet another answer; nor is yes used in one of the comments.

Still, we can reproduce yes n with a while loop. This leads to the following POSIX solution:

while true; do echo n; done | cp -Ri /origin /destination 2>/dev/null
5

Use cp -rn <sourcedirname>/. <destdirname>

The r switch makes the copy recursive over the directories.

The n switch (long version no-clobber) ensures existing files are never over-written.

The '/.' after the sourcedirname ensures that it does not become a subdirectory under the destdirname instead of all contents of the former being copied to the latter.

1
  • Thank you, your solution works for me. I used rsync and rsync ate my full cpu, my computer was too hot in high temperature, so I prefer using cp.
    – Bảo Nam
    Jan 21, 2020 at 3:08
4

Look up the "-u" option for the cp command.

1
  • 3
    Disagree that using -u is a good idea. -u copies only when source is newer or destination is missing. Original poster's issue was caused by file copy breaking for whatever reason. OP would therefore have half-written file that wasn't updated when re-running the copy. That file might be important to someone! rsync solves this problem.
    – hazymat
    Dec 21, 2013 at 21:47
2

All above answers are correct but if you are doing this recursively then

you should do:

 cp -rn SOURCE_PATH DESTINATION_PATH
1

You should be copying as root to maintain permissions/ownership

# cp -au

Also look at rsync

0

If your source location is a remote file system, and you don't have shell access to it (and thus can't use rsync), then this might help:

cd /local/destination/path
echo "reget /remote/source/path" | sftp -r sftp://username@domainOrIpAddress

From this answer.

Note that reget is the same as get -a. It checks for the presence of half-copied files and finishes copying them.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .