根据内容查找文件的重复项

根据内容查找文件的重复项

我目前正在尝试获取一个文件(图像文件,例如 test1.jpg),并且需要列出该文件的所有重复项(按内容)。我试过了,fdupes但这样无法以输入文件为基础进行检查。

TLDR:我需要一种方法来根据内容列出特定文件的所有重复项。

最好通过命令行寻找解决方案,但完整的应用程序也可以。

答案1

首先找到文件的 md5 哈希值:

$ md5sum path/to/file
e740926ec3fce151a68abfbdac3787aa  path/to/file

(第一行是您需要执行的命令,第二行是该文件的 md5 哈希值)

然后复制哈希(在您的情况下它会有所不同)并将其粘贴到下一个命令中:

$ find . -type f -print0 | xargs -0 md5sum | grep e740926ec3fce151a68abfbdac3787aa
e740926ec3fce151a68abfbdac3787aa  ./path/to/file
e740926ec3fce151a68abfbdac3787aa  ./path/to/other/file/with/same/content
....

如果你想要更高级一点,可以将这两者组合成一个命令:

$ find . -type f -print0 | xargs -0 md5sum | grep `md5sum path/to/file | cut -d " " -f 1`
e740926ec3fce151a68abfbdac3787aa  ./path/to/file
e740926ec3fce151a68abfbdac3787aa  ./path/to/other/file/with/same/content
....

如果您愿意,可以使用 sha1 或任何其他花哨的哈希值。

编辑

如果用例是在“几个多 GB 的 MP4 或 iso 文件”中搜索以找到“4 KB jpg”(根据@Tijn 的回答),那么指定文件大小将大大加快速度。

如果您要查找的文件大小正好是 3952 字节(您可以看到,使用ls -l path/to/file该命令的执行速度会更快:

$ find . -type f -size 3952c -print0 | xargs -0 md5sum | grep e740926ec3fce151a68abfbdac3787aa
e740926ec3fce151a68abfbdac3787aa  ./path/to/file
e740926ec3fce151a68abfbdac3787aa  ./path/to/other/file/with/same/content

c注意大小后面的额外内容,表示字符/字节。

如果你愿意,你可以将它们组合成一个命令:

FILE=./path/to/file && find . -type f -size $(du -b $FILE | cut -f1)c -print0 | xargs -0 md5sum | grep $(md5sum $FILE | cut -f1 -d " ")

答案2

使用差异带有布尔运算符的命令&&||

bash-4.3$ diff /etc/passwd passwd_duplicate.txt > /dev/null && echo "SAME CONTENT" || echo "CONTENT DIFFERS"
SAME CONTENT

bash-4.3$ diff /etc/passwd TESTFILE.txt > /dev/null && echo "SAME CONTENT" || echo "CONTENT DIFFERS"
CONTENT DIFFERS

如果您想要遍历特定目录中的多个文件,cd可以使用for如下循环:

bash-4.3$ for file in * ; do  diff /etc/passwd "$file" > /dev/null && echo "$file has same contents" || echo "$file has different contents"; done
also-waste.txt has different contents
directory_cleaner.py has different contents
dontdeletethisfile.txt has different contents
dont-delete.txt has different contents
important.txt has different contents
list.txt has different contents
neverdeletethis.txt has different contents
never-used-it.txt has different contents
passwd_dulicate.txt has same contents

对于递归情况,使用find命令遍历目录及其所有子目录(注意引号和所有适当的斜杠):

bash-4.3$ find . -type f -exec sh -c 'diff /etc/passwd "{}" > /dev/null &&  echo "{} same" || echo "{} differs"' \;
./reallyimportantfile.txt differs
./dont-delete.txt differs
./directory_cleaner.py differs
./TESTFILE.txt differs
./dontdeletethisfile.txt differs
./neverdeletethis.txt differs
./important.txt differs
./passwd_dulicate.txt same
./this-can-be-deleted.txt differs
./also-waste.txt differs
./never-used-it.txt differs
./list.txt differs

答案3

您可以使用文件命令Python

例如:

import filecmp 
print filecmp.cmp('filename.png', 'filename.png') 

将打印真的如果相等,否则错误的

答案4

如果您对命令行的输入流进行一些操作,则可以在命令行上使用选项-c。以下命令不是递归的,它仅在当前工作目录中起作用。替换为您希望检查重复项的文件名。md5sumoriginal_file

(hash=$(md5sum original_file) ; for f in ./* ; do echo "${hash%% *} ${f}" | if md5sum -c --status 2>/dev/null ; then echo "$f is a duplicate" ; fi ; done)

您可以替换该for f in ./*部分以for f in /directory/path/*搜索不同的目录。

如果您希望搜索通过目录进行递归,您可以设置 shell 选项“globstar”,并在 for 循环给出的模式中使用两个星号:

(shopt -s globstar; hash=$(md5sum original_file); for f in ./** ; do echo "${hash%% *} ${f}" | if md5sum -c --status 2>/dev/null; then echo "$f is a duplicate"; fi; done)

这两个版本的命令都只会使用语句 输出重复文件的名称./file is a duplicate。它们都封装在括号中,以避免在命令本身之外设置哈希变量或 globstar shell 选项。该命令可以使用其他哈希算法,例如sha256sum,只需替换 的两个出现md5sum即可实现此目的。

相关内容