对比两个目录,找出有区别的文件【仅文件名,不是内容】
比如:在一个目录下有,在另一个目录下没有都算在内
diff仅输出文件名
我正在寻找运行Linux命令,它将递归地比较两个目录并输出 仅 不同的文件名。这包括一个目录中存在的任何内容而不是另一个目录中的任何内容,反之亦然,以及文本差异。
回答1:
从diff手册页:
-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
回答2:
您也可以使用rsync
rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out
回答3:这个重点
如果要获取仅在一个目录而不是其子目录中的文件列表,并且只获取其文件名:
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
让我用这个例子来解释一下:我们想要比较两个dokuwiki版本,看看哪些文件被更改,哪些文件是新创建的。
我们用wget获取tars并将它们提取到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
使用theses参数运行:
-r
“递归到目录”,-c
还比较相同大小的文件,只“基于校验和跳过,而不是模态时间和大小”,-n
“执行试运行而不进行任何更改”,以及--out-format="%n"
为“使用指定的FORMAT输出更新”,此处仅为“%n”,仅用于文件名
两个方向上rsync
的输出(文件列表)被组合并使用sort
进行排序,然后通过使用uniq
删除所有重复项来压缩此排序列表。
在我的linux系统上获取 只是 文件名
diff -q /dir1 /dir2|cut -f2 -d' '
Linux:比较目录结构而不比较文件
Linux:比较目录结构而不比较文件
比较两个目录结构而不实际比较文件中数据的最佳和最简单方法是什么?这工作正常:
diff -qr dir1 dir2_
但这确实很慢,因为它也在比较文件。是否有一个用于diff的开关或另一个简单的cli工具来做到这一点?
-type d
从@slartibartfast的答案中删除该选项,或者查看我的答案。Answers:
以下内容(如果您将第一个目录替换为directory1,将第二个目录替换为directory2)应立即执行所需的操作:
find directory1 -type d -printf "%P\n" | sort > file1
find directory2 -type d -printf "%P\n" | sort | diff - file1
基本原理是,它打印出所有目录,包括相对于基本目录N目录的子目录路径。
如果您在某些目录名称中有回车符,而在其他目录中没有回车符,则可能会下降(产生奇怪的输出)。
diff -rq
只是显示根目录存在于其中,然后继续。vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)
将为您很好地并排显示两个目录层次结构,并折叠所有公共部分。
我通常rsync
用于此任务:
rsync -nav --delete DIR1/ DIR2
请务必始终使用-n
,aka--dry-run
,选项,否则它将同步(更改目录的内容)。
这将根据文件修改时间和大小比较文件...我想这就是您真正想要的,或者至少您不介意这样做吗?我感觉到您只是希望它发生得更快,而不是您需要它忽略文件内容之间的差异。如果您确实希望它不列出具有相同名称的不同文件,那么我认为添加该--ignore-existing
选项即可。
另外要注意,不要把一个/
在结束DIR1
将导致其比较目录 DIR1
与内容的DIR2
。
输出最终有点冗长,但是它将向您显示哪些文件/目录不同。存在于DIR2
和不存在于其中的文件/目录DIR1
将以单词开头deleting
。
在某些情况下,@ slartibartfast的答案可能更合适,尽管您需要删除-type d
启用非目录文件列表的选项。 rsync
如果您要比较的文件/目录数量很多,则速度会更快。
deleting...
文本,但这可能是在保持速度的同时比较文件的更好方法之一。当不需要差异文件时,这里的其他答案会更快...就像在OP的示例中一样,但我真的很喜欢这一点。sudo -u nobody rsync -nav --delete d1 d2
前提是“其他”的标志允许阅读。与ls答案类似,但是如果您安装树,则可以
tree dir1 > out1
tree dir2 > out2
diff out1 out2
diff <( tree dir1 ) <( tree dir2 )
i
标志的树,该标志不会显示树线(tree -i dir1
,等)。如果目录结构在一个地方不同,则匹配的其他文件|
在树输出中可能会有更多或更少的符号,即使文件路径相同,diff也会捕获这些行。我只是在寻找解决此问题的方法。我最喜欢的解决方案是:
comm <(ls DIR1) <(ls DIR2)
它为您提供3列:1-仅在DIR1中的文件,2-仅在DIR2中的文件,3-仅在DIR3中的文件有关更多详细信息,请参阅此博客文章。
DIR3
指定在哪里?我所看到的是DIR1
和DIR2
。DIR1
在第1列,只有在所有文件DIR2
中的第2列,和所有文件通过共享双方在第3列。这很有用,但是您知道如何去除第3列并仅保留差异吗?我要整理的文件很多,而且大多数文件是相同的。我不需要看看有什么相同。comm <(ls DIR1) <(ls DIR2)
递归无效。为此我用comm <(ls -R1 DIR1) <(ls -R1 DIR2)
。ls -R
递归地浏览目录,并且ls -1
(请注意那是一个,而不是L)使ls
每行仅打印一个文件名。comm -3
请参阅参考资料man comm
)。ls > dir1.txt
ls > dir2.txt
然后只比较两个列表。
这是最佳解决方案
diff --brief -r dir1 dir2
--brief开关仅报告文件是否不同,而不报告差异的详细信息。
-q
在问题中存在,这是的别名--brief
。该答案未提供任何新信息。But it's really slow because it's comparing files too.
使用“ diff -qr”获取不同的文件,然后使用grep过滤掉文件比较,以便仅获取仅在目录之一中的文件名。
diff -qr dir1 dir2 | grep -v "Files.*differ"
我认为只有rsync是userfull。为什么?
diff仅对保留文件和目录的结构有用。当我们使用符号链接时,Diff没有给出足够的退出代码。在这种情况下,即使src和dst相同(时间,大小,名称,时间戳,指向软链接等),diff也可以返回2个退出代码。
dir,即使src和dst上的目录内容相同,文件系统也不保证文件顺序。也许您应该通过排序对ls输出进行过滤。但是纯ls仅显示节点名称。
也许包括diff,cmp,test -X的节点类型的脚本将很有用,但请记住许多test / cmp运行造成的过载。该脚本将非常慢。
像往常一样,如果要获取简单的信息“目录是否相同”,则应将rsync与-n(干)选项一起使用。如果要查找不同之处,请使用diff命令。
posted on 2020-07-20 17:22 ZhYQ_note 阅读(3003) 评论(0) 编辑 收藏 举报