rsync比较目录?


Answers:


46

您可能必须rsync -avun --delete在两个方向上都运行类似的东西 。

但是您实际上想完成什么?

更新

rsync -avun --delete $TARGET $SOURCE |grep "^deleting " 将为您提供目标目录中不存在的文件列表。

“grep的DELET”,因为每行打印:DELET荷兰国际集团..file ..

rsync -avun $SOURCE $TARGET 将为您提供“不同”文件(包括新文件)的列表。


49

为了增加Nils的答案(对于通过Google遇到此问题的任何人),默认情况下,rsync仅比较文件大小和修改时间以判断是否存在差异。(如果这些不同,则执行更多操作,但是如果它们相同,则停止在此处。)

如果要比较实际文件内容,即使对于具有相同大小和最后修改时间的文件,请添加标志-c以告诉rsync您使用校验和来比较文件。

rsync -avnc $SOURCE $TARGET

(该-u选项告诉rsync忽略$TARGET比on 更新的文件,$SOURCE如果您要比较内容,则可能不希望看到这些文件。)


6
如果您只关心数据相同,则可以根据需要添加数据--no-group --no-owner --no-perms --no-times或将这些数据进行某种组合。
flungo

1
@flungo,或仅使用隐含的选项的子集来-a代替-a,例如rsync -rlDcnv --delete $SOURCE $TARGET
maxschlepzig

请将--delete仅存在于$TARGET
Tom Hale的

25

只适合那些不太熟悉的人rsync

rsync -rvnc --delete ${SOURCE}/ ${DEST}
  • -n:最重要的一点-你不能改变任何东西;
  • -rc:只比较内容(否则用-ac);
  • -v :列出文件)
  • --delete :寻找对称的差异,而不是单向的差异。
  • 最后,/意思是“查看目录,并将其内容与目标进行比较”。

它将打印出通常的rsync输出,

  • 一行中的每个“新”文件都带有一个<filename>${SOURCE}
  • 并为中的每个“新”文件添加一个“删除<文件名>”${DEST}

  • 它还可能会显示一些警告,例如符号链接的“跳过非常规文件<文件名>”

PS。我知道这是一个糟糕的PS,但确实是匆忙添加了。不过,我敢打赌,这可能会有用。


PPS。或者,也可以

find $SOURCE -type f -exec md5sum {} \; | tee source.md5
find $DEST   -type f -exec md5sum {} \; | tee dest.md5

如果文件名不包含换行符,则可以对两个*.md5文件和diff它们进行排序。(不过,这仅适用于文件;也就是说,不会检测到两侧的空目录。)


15

令人惊讶的是,六年来没有答案使用该-i选项或给出了很好的输出,所以在这里我去:

TLDR-仅显示命令

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 /'

了解输出

这是输出示例:

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表示文件/目录仅出现在Left或Right目录中。
  • X意味着该文件出现在两侧,但是是不一样的(在这种情况下,接下来的11个字符给你更多的信息。stp描绘了不同小号 IZE,牛逼 IME和p分别ermissions -更多的信息尝试man rsync和搜索--itemize-changes) 。

您可能希望使用的其他选项

如果还想比较文件的所有者/组/权限,则分别添加选项-o/ -g/ -p。最后请注意,默认情况下,rsync认为两个文件的名称,时间和大小相同时,它们是相同的。这是非常快的,并且在大多数情况下已经足够了,但是如果您想100%确保添加-c,还可以比较具有相同名称,时间和大小的文件的内容。

TLDR-给我一个脚本来打电话

这里是。这样称呼它

diff-dirs Left_Dir Right_Dir [options]

上文“您可能希望使用的其他选项”部分中提到的所有选项也适用于此。

#!/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 /'

它是如何工作的?

我们这样称呼rsync:

rsync -rin ...

我们使用-i--itemize-changes)告诉rsync为包含有关两个目录之间任何差异的信息的每个文件打印一行输出。我们需要-n抑制rsync的正常行为(即试图通过复制/删除文件来同步两个目录)。我们还需要-r递归地处理所有文件/子目录。

我们称呼rsync 3次:

第一次调用:打印Dir_B中不存在的文件。我们需要使用--ignore-existing忽略双方都存在的文件。

rsync -rin --ignore-existing $DIR_A/ $DIR_B/

第二次通话:与之前完全相同,但我们交换了DIR_A / DIR_B的顺序。

第三次通话:最后,我们--existing只检查两个目录中都出现的文件。

rsync -rin --existing $DIR_A/ $DIR_B/

不了解其他人,但是我正在使用您的脚本。做得好!谢谢
Marinaio

7

我从您的问题中了解到,您不想在ls上使用diff ,但也可以在目录上递归使用diff:

diff -rq DIR1 DIR2

2

我花了一些努力才能使它生效。Nils的答案要求$TARGET以尾随结尾/,如ジョージ所解释。

这是显式添加结尾的版本/

rsync -avun --delete ${TARGET}/ ${SOURCE}  | sed -ne 's/^deleting *//p'

这给出了存在于${SOURCE}目录下但不在目录下的文件列表${TARGET}

sed在这里使用以删除deleting输出行中的开头,并仅打印那些行。

我不使用该rsync选项,-c因为在我的用例中比较文件内容会慢很多,而在这些情况下仅比较文件大小和修改时间似乎也足够了。我没有理由怀疑我的计算机遭受时钟偏斜问题或某些恶意更改的时间戳记。同样,的结果-c不能更改删除文件的决定,只能更改更新或保留文件的决定。

我还使用-u-a(而不是-r),以便以后可以重新使用命令行并将其更改为将选定的目录和文件从复制${SOURCE}${TARGET},如下所示:

rsync -avu ${SOURCE}/{dirA,dirB,fileX} ${TARGET}   # copy some files

0

我有这样做的另一个想法:

rsync -rn --out-format=FILEDETAIL::%n  $TARGET $SOURCE  | grep "^FILEDETAIL"

您可以将“ FILEDETAIL ::”与命令的输出匹配。另外,您可以更改字符串“ FILEDETAIL ::”。“%n”是文件名。

-r这告诉rsync递归复制目录。

-n使rsync执行不做任何更改的试运行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.