Surprisingly no answer in 6 years uses the -i
option or gives nice output so here I'll go:
TLDR - Just show me the commands
rsync -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L /'
rsync -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R /'
rsync -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'
Understanding the output
Here's an example of the output:
L file-only-in-Left-dir
R file-only-in-right-dir
X >f.st...... file-with-dif-size-and-time
X .f...p..... file-with-dif-perms
Note the first character of every line:
L
/R
mean that the file/dir appears only at the L
eft or R
ight dir.
X
means that the file appears on both sides but is not the same (in which case the next 11 characters give you more info. s
,t
and p
depict differences in size, time and permissions respectively -- for more info try man rsync
and search for --itemize-changes
).
Extra options you may wish to use
If you want to also compare the owner/group/permissions of the files add the options -o
/-g
/-p
respectively. Finally note that by default rsync considers two files the same if they have the same name, time and size. This is extremely fast and most of the times more than enough but if you want to be 100% sure add -c
to also compare the contents of files with the same name, time & size.
TLDR - Just give me a script to call
Here it is. Call it like this
diff-dirs Left_Dir Right_Dir [options]
All options mentioned above in section "Extra options you may wish to use" also apply here.
#!/bin/bash
# Compare two directories using rsync and print the differences
# CAUTION: options MUST appear after the directories
#
# SYNTAX
#---------
# diff-dirs Left_Dir Right_Dir [options]
#
# EXAMPLE OF OUTPUT
#------------------
# L file-only-in-Left-dir
# R file-only-in-right-dir
# X >f.st...... file-with-dif-size-and-time
# X .f...p..... file-with-dif-perms
#
# L / R mean that the file/dir appears only at the `L`eft or `R`ight dir.
#
# X means that a file appears on both sides but is not the same (in which
# case the next 11 characters give you more info. In most cases knowing
# that s,t,T and p depict differences in Size, Time and Permissions
# is enough but `man rsync` has more info
# (look at the --itemize-changes option)
#
# OPTIONS
#---------
# All options are passed to rsync. Here are the most useful for the purpose
# of directory comparisons:
#
# -c will force comparison of file contents (otherwise only
# time & size is compared which is much faster)
#
# -p/-o/-g will force comparison of permissions/owner/group
if [[ -z $2 ]] ; then
echo "USAGE: $0 dir1 dir2 [optional rsync arguments]"
exit 1
fi
set -e
LEFT_DIR=$1; shift
RIGHT_DIR=$1; shift
OPTIONS="$*"
# Files that don't exist in Right_Dir
rsync $OPTIONS -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L /'
# Files that don't exist in Left_Dir
rsync $OPTIONS -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R /'
# Files that exist in both dirs but have differences
rsync $OPTIONS -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'
How does it work?
We're calling rsync like this:
rsync -rin ...
We use -i
(--itemize-changes
) to tell rsync to print one line of output for every file that contains information about any differences between the two directories. We need -n
to suppress normal behavior of rsync (which is to try to sync the two dirs by copying/deleting files). we also need -r
to work recursively for all files/sub-dirs.
We call rsync three times:
1st call: print files that don't exist in Dir_B. We need to use --ignore-existing
to ignore files that exist on both sides.
rsync -rin --ignore-existing $DIR_A/ $DIR_B/
2nd call: Exactly as before but we swap the order of DIR_A/DIR_B.
3rd call: Finally we use --existing
to only check files that appear in both dirs.
rsync -rin --existing $DIR_A/ $DIR_B/