14

I'm creating a simple script that copies all files from DIRECTORYA that do not exist in DIRECTORYB. I'm doing this through the use of the cp command:

cp -u DIRECTORYA/* DIRECTORYB

What I'd like to do is also send an email to an administrator that will list the files that have been copied.

So ideally, before I run the above command, I'd like to get the files that will be copied and store them in a variable for later use when building my email message.

Can anybody point me in the right direction? I've looked into using grep but I don't think this can be done with the cp command?

4
  • 1
    Maybe I'm misunderstanding your question, but can't you use the -v flag, to print the filenames as they are copied? Redirect that to a file or directly in a variable and use that to build your message. Mar 3 '15 at 16:15
  • Additionally the cp command has option --attributes-only wich allow to do not copy files data, but just directory and files structure.
    – Costas
    Mar 3 '15 at 16:18
  • Sorry I'm fairly new to scripting. If I use the -v flag, how can I output to a variable instead of a file?
    – James
    Mar 3 '15 at 16:40
  • 1
    Assuming you are using bash, variable=$(cp -v ...) captures the stdout of cp. See gnu.org/software/bash/manual/html_node/Command-Substitution.htm
    – Gowtham
    Mar 3 '15 at 17:32
7

I don't think GNU cp has anything to help you if you want to see what it would do without acting. If you want to log the files that were modified, you can use the -v option:

cp -puv DIRECTORYA/* DIRECTORYB >copy.log

Instead of cp, you can use rsync, which is a lot more powerful and installed almost everywhere except for low-end embedded systems (and easy to install where it isn't present by default).

rsync -aunv DIRECTORYA/* DIRECTORYB >what-would-be-done.txt

or

rsync -auv DIRECTORYA/* DIRECTORYB >copy.log
4
  • I wonder if the find command couldn't be tailored to work like the cp command. I'm gonna give that a try this week. If you have any caveats in advance that would be very much appreciated. Jun 24 '20 at 22:54
  • @WinEunuuchs2Unix Sure, you can run find inside both DIRECTORYA and DIRECTORYB and compare the output. I'm sure the code to do this has been posted multiple times on this site. Jun 25 '20 at 8:20
  • rsync is great, thanks this is my preferred solution.
    – Merlin
    Aug 17 at 1:36
  • NOTE: rsync -aun (aka rsync --archive --update --dry-run) will print nothing, you need to add the --verbose/-v flag to get your dry run output. Maddening, but now you know (rsync version 3.2.3 protocol version 31). rsync is still awesome.
    – Merlin
    Aug 17 at 2:48
6

According to the manual page,

-u, --update
copy only when the SOURCE file is newer than the destination file or when the destination file is missing

this is a feature which combines two tests, one trivial to implement in a script (missing) and one requiring some work (newer). You could make a script which reports what is needed using comm, diff and test.

None of the standard cp utilities provide the ability to dry-run a copy operation. As suggested, rsync is the way to do this with a commonly-available utility. Of course, rsync is usually used to copy based on more criteria than just newer or missing (file size and timestamps also are used). But it can be reduced to doing just cp -u.

For non-standard utilities, there's the copy utility which I wrote (and of course still use) in the late 1980s. It was probably inspired by the make utility, since the first option I added was -n.

For the given example, it would be used like this:

$ copy -nvU DIRECTORYA/* DIRECTORYB
** copy DIRECTORYA/foo to DIRECTORYB/foo
** 1 file would be copied, 616 bytes

Further reading:

  • copy - file/directory copy utility

    -n disables the actual creation or modification of files, and (depending on the level of verboseness) shows the effect which the copy command would have.
    -u copies files only if their size or modification date differs, and links only if the link-text differs.
    -U copies only files that are newer than the destination, or that do not exist in the destination.

  • changelog entry from August 1988:

    1988-08-16    
            * src/copy/src/copy.c: added "-d" and "-n" options.
    
2

If you wanted to run cp foo*bar whatever, then run echo foo*bar whatever instead.

1
  • 1
    But OP wants to run cp -u and he's looking for a dry-run like option for cp. Mar 3 '15 at 20:58
0

You can use diff command. I have a job that copy some backup files everyday. some time I need to check if all files are copied, here is the syntax:

diff /file1/ /file2/

and of course if you want to copy them use:

cp -u /file1/* /file2
0

Consider using rsync instead. Rsync works perfectly well on local copies and can certainly do what you want, once you wade through the fifteen gazillion options it has.

rsync -avun DIRECTORYA/ DIRECTORYB

will show you everything that would be done, and

rsync -avu DIRECTORYA/ DIRECTORYB

will do it.

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.