I am using rsync in a bash script to keep files in sync between a few servers and a NAS. One issue I have run into is trying to generate a list of the files that have changed from the during the rsync.

The idea is that when I run rsync, I can output the files that have changed into a text file - more hoping for an array in memory - then before the script exists I can run a chown on only the changed files.

Has anyone found a way to perform such a task?

# specify the source directory
source_directory=/Users/jason/Desktop/source

# specify the destination directory
# DO NOT ADD THE SAME DIRECTORY NAME AS RSYNC WILL CREATE IT FOR YOU
destination_directory=/Users/jason/Desktop/destination

# run the rsync command
rsync -avz $source_directory $destination_directory

# grab the changed items and save to an array or temp file?

# loop through and chown each changed file
for changed_item in "${changed_items[@]}"
do
        # chown the file owner and notify the user
        chown -R user:usergroup; echo '!! changed the user and group for:' $changed_item
done
up vote 35 down vote accepted

You can use rsync's --itemize-changes (-i) option to generate a parsable output that looks like this:

~ $ rsync src/ dest/ -ai
.d..t.... ./
>f+++++++ newfile
>f..t.... oldfile

~ $ echo 'new stuff' > src/newfile

~ $ !rsync
rsync src/ dest/ -ai
>f.st.... newfile

The > character in the first position indicates a file was updated, the remaining characters indicate why, for example here s and t indicate that the file size and timestamp changed.

A quick and dirty way to get the file list might be:

rsync -ai src/ dest/ | egrep '^>'

Obviously more advanced parsing could produce cleaner output :-)

I came across this great link while trying to find out when --itemize-changes was introduced, very useful:

http://andreafrancia.it/2010/03/understanding-the-output-of-rsync-itemize-changes.html (archived link)

  • 1
    For a cleaner output as mentioned, rsync -zaic src/ dest/ | grep '^?c' | cut -d' ' -f2 --dry-run would only list the modified files (different checksum) , definitely a keeper, thx :) FYI putting --dry-run after the command instead of using the n option is for me a best practice – MediaVince Dec 23 '16 at 9:37
  • Essentially the same as rsync -zavc src/ dest/ --dry-run without verbose – MediaVince Dec 23 '16 at 9:45

Use the -n flag, combined with the -c checksum flag and the -i flag:

# rsync -naic test/ test-clone/
>fcst...... a.txt
>fcst...... abcde.txt
>fcst...... b.txt

In this example, only one file has changed, based on the contents of the file itself. However, no file syncing is done because of the -n flag

Bonus

If you want to run chown on the changed files, parse them out with sed or similar and process with xargs, for example:

rsync -naic test/ test-clone/ | sed 's/............//' | xargs -I+ sudo chown root "test-clone/+"
  • 3
    sed -> cut -d ' ' -f2,- – MUY Belgium Jun 21 '16 at 12:01
  • -n --dry-run, -c --checksum, -i --itemize-changes – ThorSummoner Aug 18 at 20:12

This question is a little bit old, but I think it worth to be added:

-i is a shortcut of --out-format=%i%n%L

And %n means the filename, (section log format of man rsyncd.conf)

P.S. rsync version 3.1.0

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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