rsync 比较目录?

chr*_*ris 86 directory rsync file-comparison

是否可以使用 rsync 比较两个目录并仅打印差异?有一个试运行选项,但是当我将详细程度增加到一定程度时,会显示每个比较的文件。

ls -alR并且diff在这里没有选择,因为源中有硬链接使每一行都不同。(当然,我可以用 perl 删除此列。)

小智 63

要添加到 Nils 的答案(对于通过 Google 遇到此问题的任何人),默认情况下rsync仅比较文件大小和修改时间以判断是否存在任何差异。(如果它们不同,它会做得更多,但如果它们相同,它就会停在那里。)

如果要比较实际文件内容,即使是大小和上次修改时间相同的文件,也可以添加标志-c以告诉rsync使用校验和比较文件。

rsync -avnc $SOURCE $TARGET
Run Code Online (Sandbox Code Playgroud)

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

  • 如果您只关心数据是否相同,您可能需要根据您的需要添加 `--no-group --no-owner --no-perms --no-times` 或这些的某种组合。 (7认同)
  • @flungo,或者只使用`-a` 隐含的选项的子集而不是`-a`,例如`rsync -rlDcnv --delete $SOURCE $TARGET` (2认同)
  • 请添加“--delete”以列出仅存在于“$TARGET”中的文件 (2认同)
  • 您需要在源末尾添加“/”,但不是目标:“rsync -avnc $SOURCE/ $TARGET” (2认同)

Nil*_*ils 55

你可能不得不rsync -avun --delete在两个方向上运行类似的东西 。

但是你实际上想要完成什么?

更新

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

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

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


ジョー*_*ョージ 41

只为那些不太熟悉的人rsync

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

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

  • 中的每个“新”文件在一行上都有一个<filename>${SOURCE}
  • . 中的每个“新”文件都有一个“删除 <文件名>”${DEST}

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

附注。我知道这是一个糟糕的 PS——但它确实是匆忙添加的。尽管如此,我敢打赌人们可能会发现这很有用。


聚苯乙烯。或者,也可以这样做

find $SOURCE -type f -exec md5sum {} \; | tee source.md5
find $DEST   -type f -exec md5sum {} \; | tee dest.md5
Run Code Online (Sandbox Code Playgroud)

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

  • SOURCE 中的 `/` 很重要......并且 DEST 中也没有它! (7认同)

nde*_*mou 31

令人惊讶的是,6 年内没有答案使用该-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 /'
Run Code Online (Sandbox Code Playgroud)

了解输出

下面是一个输出示例:

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
Run Code Online (Sandbox Code Playgroud)

注意每一行的第一个字符:

  • 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]
Run Code Online (Sandbox Code Playgroud)

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

#!/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 /'
Run Code Online (Sandbox Code Playgroud)

它是如何工作的?

我们像这样调用 rsync:

rsync -rin ...
Run Code Online (Sandbox Code Playgroud)

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

我们调用 rsync 3 次:

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

rsync -rin --ignore-existing $DIR_A/ $DIR_B/
Run Code Online (Sandbox Code Playgroud)

第二次调用:与以前完全一样,但我们交换了 DIR_A/DIR_B 的顺序。

第三次调用:最后我们--existing只检查出现在两个目录中的文件。

rsync -rin --existing $DIR_A/ $DIR_B/
Run Code Online (Sandbox Code Playgroud)

  • 不知道其他人,但我正在使用您的脚本。做得好!谢谢 (3认同)
  • 有趣的剧本!需要注意的一件事:该脚本对包含非常规文件的目录存在问题:它们似乎列在左侧、右侧和已更改的部分中! (2认同)

小智 13

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

diff -rq DIR1 DIR2
Run Code Online (Sandbox Code Playgroud)