我的目录中有许多文件,我想检查它们是否都是唯一的。为简单起见,假设我有三个文件:foo.txt
、bar.txt
和baz.txt
。如果我运行这个循环,我将相互检查它们:
$ for f in ./*; do for i in ./*; do diff -q "$f" "$i"; done; done
Files bar.txt and baz.txt differ
Files bar.txt and foo.txt differ
Files baz.txt and bar.txt differ
Files baz.txt and foo.txt differ
Files foo.txt and bar.txt differ
Files foo.txt and baz.txt differ
对于我想要处理的数百个文件,这将变得非常不可读;最好列出这些文件做匹配,然后我可以快速查看列表并确保文件仅与自身匹配。从联机帮助页来看,我本以为该-s
选项可以完成此任务:
$ for f in ./*; do for i in ./*; do diff -s "$f" "$i"; done; done
Files bar.txt and bar.txt are identical
Files baz.txt and baz.txt are identical
Files foo.txt and foo.txt are identical
……然而事实上还打印出任何不同文件的全部内容。有什么办法可以抑制这种行为,所以我只能得到上面的行为?
或者,有没有其他一些可以完成此任务的工具?
答案1
这应该可以解决问题:
diff -rs dir1 dir2 | egrep '^Files .+ and .+ are identical$'
其中dir1
和dir2
是你的两个目录。
如果您只想打印以下位置的匹配目录dir1
:
diff -rs dir1 dir2 | egrep '^Files .+ and .+ are identical$' | awk -F '(Files | and | are identical)' '{print $2}'
同样,如果您只想打印以下位置的匹配目录dir2
:
diff -rs dir1 dir2 | egrep '^Files .+ and .+ are identical$' | awk -F '(Files | and | are identical)' '{print $3}'
答案2
如果您只想检查两个文件是否相同,请使用cmp
.要仅获取相同文件的输出,您可以使用
for f in ./*; do for i in ./*; do cmp -s "$f" "$i" && echo "Files $f and $i are identical"; done; done
diff
尝试生成一个简短的、人类可读的差异列表,这可能需要相当多的时间,因此如果不需要它,请避免开销。
答案3
这最快的为此目的编写的工具是复制品(它可以在 Fedora 和 Ubuntu 的软件包存储库中找到……)
用法:
fdupes -r dir1 dir2
答案4
如果您需要在列表中查找相同的文件,请首先按大小对它们进行排序,例如使用
ls -S
然后,对于每组相同大小的文件,运行md5sum
它们以轻松查看哪些文件相同。
对于大文件,可以更快地仅对整个文件的一小部分进行首次校验:
dd if=file bs=512 count=1 | md5sum
然后仅对可疑文件执行完整的校验和。