The hidden danger of using rsync to copy files instead of cp

I have a long standing reflexive habit that most of them time when I want to copy files around, I reach for ' rsync -a ' by default. I do it on the command line, and I do it in things like our local postinstall system setup scripts . It's not really necessary these days (' cp -a ' now works fine on everything I commonly use), but I started doing this in an era when rsync was the clearly safest choice for a 'copy file, preserving all attributes, no matter what system I'm on' command. Today I made a mistake and was reminded that this is not necessarily the best idea, because there is a small difference in behavior between rsync and cp here.

What happened today is that in a system setup script, I wrote:

set -e
[...]
rsync -a /master/loc/etc/cron.d/cron-thing /etc/crond.d/

I ran the script, it went fine, and then afterward the system didn't actually seem to be doing what the cron.d entry was supposed to have it do. I spent some time wondering if I'd gotten some other bit of the system setup wrong, so that the script I was invoking from cron couldn't do anything, and then finally I looked in /etc/cron.d for some reason and the penny dropped.

You see, the important difference between rsync and cp here is that rsync will create a destination directory if necessary and cp won't . The drawback of this sometimes-handy behavior is that rsync's behavior hides typos . Had I written ' cp -a ... /etc/cron d .d/ ', the cp would have errored out (and then the entire script would have aborted). With rsync , it quietly created /etc/crond.d and put my cron-thing in it, just as I'd typed but not as I'd wanted.

After this happened, I went back through this script and turned all of my reflexive ' rsync -a ' usage into ' cp -a '. I've been burned once, I don't need to stub my toe a second time . I don't currently plan to revise our existing (working) scripts just for this, but certainly I'm now going to try to shift my reflexes and use ' cp -a ' in the future.

(In this sort of context, even if I want the directory created too I think it's better to use ' mkdir -p ' in order to be explicit about it. On the command line I might exploit rsync 's side effect, but in a script there's no reason to be that compact and obscure.)