Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm doing this sync locally on Ubuntu 12.04. The files are generally small text files (code).

I want to copy (preserving mtime stamp) from source directory to target but I only want to copy if the file in target already exists and is older than the one in source.

So I am only copying files that are newer in source, but they must exist in target or they won't be copied. (source will have many more files than target.)

I will actually be copying from source to multiple target directories. I mention this in case it impacts the choice of solution. However, I can easily run my command multiple times, specifying the new target each time, if that's what is required.

share|improve this question
add comment

1 Answer

up vote 5 down vote accepted

I believe you can use rsync to do this. The key observation would be in needing to use the --existing and --update switches.

        --existing              skip creating new files on receiver
        -u, --update            skip files that are newer on the receiver

A command like this would do it:

$ rsync -avz --update --existing src/ dst

Example

Say we have the following sample data.

$ mkdir -p src/; touch src/file{1..3}
$ mkdir -p dst/; touch dst/file{2..3}
$ touch -d 20120101 src/file2

Which looks as follows:

$ ls -l src/ dst/
dst/:
total 0
-rw-rw-r--. 1 saml saml 0 Feb 27 01:00 file2
-rw-rw-r--. 1 saml saml 0 Feb 27 01:00 file3

src/:
total 0
-rw-rw-r--. 1 saml saml 0 Feb 27 01:00 file1
-rw-rw-r--. 1 saml saml 0 Jan  1  2012 file2
-rw-rw-r--. 1 saml saml 0 Feb 27 01:00 file3

Now if I were to sync these directories nothing would happen:

$ rsync -avz --update --existing src/ dst
sending incremental file list

sent 12 bytes  received 31 bytes  406.00 bytes/sec
total size is 0  speedup is 0.00

If we touch a source file so that it's newer:

$ touch src/file3 
$ ls -l src/file3
-rw-rw-r--. 1 saml saml 0 Feb 27 01:04 src/file3

Another run of the rsync command:

$ rsync -avz --update --existing src/ dst
sending incremental file list
file3

sent 115 bytes  received 31 bytes  292.00 bytes/sec
total size is 0  speedup is 0.00

We can see that file3, since it's newer, and that it exists in dst/, it gets sent.

Testing

To make sure things work before you cut the command loose, I'd suggest using another of rsync's switches, --dry-run. Let's add another -v too so rsync's output is more verbose.

$ rsync -avvz --dry-run -update --existing src/ dst
sending incremental file list
delta-transmission disabled for local transfer or --whole-file
file1
file2 is uptodate
file3 is newer
total: matches=0  hash_hits=0  false_alarms=0 data=0

sent 88 bytes  received 21 bytes  218.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)
share|improve this answer
    
Thank you. Don't I need a few more rsync options? I'm reading the man page. Seems like I might need this: rsync --archive --update --existing --whole-file --itemize-changes a/ b. Or are most of those options unnecessary? (I added whole file because these are mostly small text files.) –  MountainX Feb 27 at 6:14
    
@MountainX - only add options you need. I'd start with -a that's a superset of switches, -rlptgoD. –  slm Feb 27 at 6:17
    
Let me clarify that. I'm confused about --update and --existing. Do I need both? I tested your solution and it seems to work, but I still feel safer adding --update . –  MountainX Feb 27 at 6:20
    
@MountainX - sure you can add it in, I'll put it in the A too. –  slm Feb 27 at 6:24
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.