diff仅输出文件名


243

我正在寻找运行一个Linux命令,该命令将递归比较两个目录并输出不同文件名。这包括一个目录中存在的所有内容,而另一目录中则不存在,反之亦然,以及文本差异。

Answers:


374

从差异手册页:

-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-CentOS 7中的手册页描述-q为“仅在文件不同时才报告”,这比您编写的内容不清楚。

2
这将比较文件的实际内容,而这通常是人们想要的,但是rsync答案提供了仅查看文件名和大小而不查看内容的选项。有时是可取的。
steveb

同样适用于macOS。
Marius Soutier

另外,可以-x PATTERN在命令中包括以排除某些子目录。例如,diff -qr repo1 repo2 -x ".git" 将比较两个目录,但将排除其中带有“ .git”的文件路径。
ViFI

27

您也可以使用rsync

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out

6
--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
iolsmit 2015年

6
如果您只是在寻找丢失的文件(尤其是跨网络共享),那会很好,因为它不比较内容。这帮助我找到了一些迁移到新NAS时失败的文件。
OverZealous 2015年

4
确保在rsync的命令行上指定的路径末尾包含斜杠。否则,这将无法正常工作,而rsync可能只会枚举所有文件名!
弗拉基米尔·潘捷列夫

2
关于不检查内容的评论。有时这是理想的,至少作为第一遍。
steveb

13

如果要获取仅在一个目录中而不在其子目录中且仅在文件名中的文件列表:

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 {}

9

在我的Linux系统上,获取文件名

diff -q /dir1 /dir2|cut -f2 -d' '

7
我没有在Linux系统上放置带空格的文件名。;)
gerardw 2014年

6
我不是要把这个
归咎于

对我不起作用。我的目录结构如下audit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
Alex Raj Kaliamoorthy

diff -qrN /dir1 /dir2 | cut -f2 -d' '对我来说很好!
弗朗切斯科

9

运行方法diff -qr old/ new/有一个主要缺点:它可能会丢失新创建的目录中的文件。例如,在下面的示例中,文件data/pages/playground/playground.txt不在diff -qr old/ new/目录的输出中,而目录不在 目录data/pages/playground/中(在浏览器中搜索park.txt以快速进行比较)。我还在Unix&Linux Stack Exchange上发布了以下解决方案,但我也将其复制到这里:

要以编程方式创建新文件或修改文件的列表,我能想到的最佳解决方案是使用rsyncsort uniq

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

让我用这个例子来解释:我们想比较两个dokuwiki版本,看看哪些文件被更改,哪些文件是新创建的。

我们使用wget提取焦油并将其提取到目录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会丢失新创建的文件,而在另一方向上运行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 还比较相同大小的文件,只比较“根据校验和跳过,而不是基于调制时间和大小”,
  • -n “不进行任何更改即可进行试运行”,并且
  • --out-format="%n" “使用指定的格式输出更新”,此处仅文件名是“%n”

rsync双向的输出(文件列表)使用进行合并和排序sort,然后通过使用删除所有重复项来压缩此排序列表。uniq


您不能仅将其向后运行(diff new/ old/)来查看删除了哪些目录?
雅克

diff -qr new/ old/在带有dokuwiki tar的上述示例上运行,将产生与-相同的输出,diff -qr old/ new/即,您看到目录是新目录/缺少目录,而不是其中的文件
iolsmit

-4
rsync -rvc --delete --size-only --dry-run source dir target dir
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.