【发布时间】:2011-09-07 05:45:11
【问题描述】:
我希望运行一个 Linux 命令,该命令将递归地比较两个目录并仅输出不同的文件名。这包括存在于一个目录中而不存在于另一个目录中的任何内容(反之亦然),以及文本差异。
【问题讨论】:
标签: linux command-line diff
我希望运行一个 Linux 命令,该命令将递归地比较两个目录并仅输出不同的文件名。这包括存在于一个目录中而不存在于另一个目录中的任何内容(反之亦然),以及文本差异。
【问题讨论】:
标签: linux command-line diff
你也可以使用rsync
rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out
【讨论】:
--size-only 将丢失大小相同但内容不同的文件,例如old/version.txt "29a" new/version.txt "29b"。改用:rsync -ric --dry-run old/ new/ 其中“-i”参数允许通过rsync -ric --dry-run old/ new/ | cut -d" " -f 2直接获取文件列表
--size-only 来检查全部内容。
rsync -rvc --delete --size-only --dry-run source dir target dir
【讨论】:
如果您想获取仅位于一个目录中而不是其子目录且仅位于其文件名中的文件列表:
diff -q /dir1 /dir2 | grep /dir1 | grep -E "^Only in*" | sed -n 's/[^:]*: //p'
如果你想递归地列出所有不同的文件和目录,它们的完整路径:
diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}'
这样您就可以对所有文件应用不同的命令。
例如,我可以删除 dir1 而不是 dir2 中的所有文件和目录:
diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}' xargs -I {} rm -r {}
【讨论】:
运行diff -qr old/ new/ 的方法有一个主要缺点:它可能会丢失新创建的目录中的文件。例如。在下面的示例中,文件data/pages/playground/playground.txt 不在diff -qr old/ new/ 的输出中,而目录data/pages/playground/ 是(在浏览器中搜索playground.txt 以快速比较)。我还发布了以下解决方案on Unix & Linux Stack Exchange,但我也将其复制在这里:
要以编程方式创建新文件或修改文件的列表,我能想到的最佳解决方案是使用 rsync、sort 和 uniq :
(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq
让我用这个例子来解释一下:我们想比较两个 dokuwiki 版本,看看哪些文件被更改,哪些文件是新创建的。
我们使用 wget 获取 tar 并将它们提取到目录 old/ 和 new/:
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1
以一种方式运行 rsync 可能会错过新创建的文件,因为 rsync 和 diff 的比较显示如下:
rsync -rcn --out-format="%n" old/ new/
产生以下输出:
VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php
只在一个方向运行 rsync 会丢失新创建的文件,反之则会丢失已删除的文件,比较 diff 的输出:
diff -qr old/ new/
产生以下输出:
Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ
双向运行 rsync 并对输出进行排序以删除重复项显示目录 data/pages/playground/ 和文件 data/pages/playground/playground.txt 最初被遗漏:
(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq
产生以下输出:
VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php
rsync 使用这些参数运行:
-r“递归到目录”,-c 还比较相同大小的文件,并且仅“基于校验和跳过,而不是 mod-time & size”,-n“在不做任何更改的情况下进行试运行”,并且--out-format="%n" 为“使用指定的格式输出更新”,此处为“%n”,仅用于文件名rsync 在两个方向上的输出(文件列表)使用sort 进行组合和排序,然后通过使用uniq 删除所有重复项来压缩此排序列表
【讨论】:
diff new/ old/) 看看哪些目录被删除了吗?
diff -qr new/ old/ 并使用 dokuwiki tar 会产生与 diff -qr old/ new/ 相同的输出——即您会看到目录是新的/丢失的,但不是其中的文件
来自差异手册页:
-q仅报告文件是否不同,而不是差异的详细信息。-r比较目录时,递归比较找到的任何子目录。
示例命令:
diff -qr dir1 dir2
示例输出(取决于语言环境):
$ ls dir1 dir2
dir1:
same-file different only-1
dir2:
same-file different only-2
$ diff -qr dir1 dir2
Files dir1/different and dir2/different differ
Only in dir1: only-1
Only in dir2: only-2
【讨论】:
diff 手册页将 -q 描述为“仅在文件不同时报告”,这不如您写的那么清楚。
-x PATTERN 以排除某些子目录。例如,diff -qr repo1 repo2 -x ".git" 将比较两个目录,但会排除其中包含“.git”的文件路径。
在我的 linux 系统上获取 文件名
diff -q /dir1 /dir2|cut -f2 -d' '
【讨论】:
audit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
diff -qrN /dir1 /dir2 | cut -f2 -d' ' 适合我!