我希望运行一个 Linux 命令,该命令将递归比较两个目录并仅输出不同的文件名。这包括一个目录中存在而不是另一个目录中存在的任何内容,反之亦然,以及文本差异。
-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
rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out
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进行快速比较)。我还在 Unix & Linux Stack Exchange 上发布了以下解决方案,但我也会将其复制到此处: 要以编程方式创建新文件或修改文件的列表,我能想到的最佳解决方案是使用 rsync、
sort 和 uniq:
(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq
我们使用 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
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
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
-n
--out-format="%n"
rsync
sort
进行组合和排序,然后通过使用
uniq
删除所有重复项来压缩此排序列表
在我的 Linux 系统上获取
diff -q /dir1 /dir2|cut -f2 -d' '
$ tree dir1
dir1
├── a
│ └── 1.txt
├── b
│ └── 2.txt
└── c
├── 3.txt
├── 4.txt
└── d
└── 5.txt
4 directories, 5 files
我还有另一个目录。
$ tree dir2
dir2
├── a
│ └── 1.txt
├── b
└── c
├── 3.txt
├── 5.txt
└── d
└── 5.txt
4 directories, 4 files
我可以区分两个目录。
$ diff <(cd dir1; find . -type f | sort) <(cd dir2; find . -type f| sort)
--- /dev/fd/11 2022-01-21 20:27:15.000000000 +0900
+++ /dev/fd/12 2022-01-21 20:27:15.000000000 +0900
@@ -1,5 +1,4 @@
./a/1.txt
-./b/2.txt
./c/3.txt
-./c/4.txt
+./c/5.txt
./c/d/5.txt
rsync -rvc --delete --size-only --dry-run source dir target dir