Python 查找名称相同但内容不同的文件

Python 查找名称相同但内容不同的文件,python,linux,sed,Python,Linux,Sed,我需要在包含大量文件的linux文件夹结构中查找名称相同但内容不同的文件 像这样的东西部分地完成了工作,我如何消除具有不同内容的文件 #!/bin/sh dirname=/path/to/directory find $dirname -type f | sed 's_.*/__' | sort| uniq -d| while read fileName do find $dirname -type f | grep "$fileName" done () 非常感谢 第一个问题是,如何确

我需要在包含大量文件的linux文件夹结构中查找名称相同但内容不同的文件

像这样的东西部分地完成了工作,我如何消除具有不同内容的文件

#!/bin/sh 
dirname=/path/to/directory
find $dirname -type f | sed 's_.*/__' | sort|  uniq -d| 
while read fileName
do
find $dirname -type f | grep "$fileName"
done
()


非常感谢

第一个问题是,如何确定两个文件的内容是否相同

一个明显的可能性是读取(或mmap)两个文件,并一次比较一个块。在某些平台上,
stat
read
快得多,因此您可能需要首先比较大小。还有其他一些优化可能很有用,具体取决于您实际执行的操作(例如,如果您要运行数千次,并且大多数文件每次都是相同的,您可以对它们进行散列并缓存散列,并且仅在散列匹配时才检查实际文件)。但如果现有代码是可接受的,我怀疑您是否太担心这种性能调整(因为它会针对树中的每个文件在整个树中搜索一次),所以让我们做最简单的事情

在Python中有一种方法可以做到这一点:

#!/usr/bin/env python3
import sys

def readfile(path):
    with open(path, 'rb') as f:
        return f.read()

contents = [readfile(fname) for fname in sys.argv[1:]]
sys.exit(all(content == contents[0] for content in contents[1:]))

如果所有文件都相同,则退出代码为1;如果任何一对文件不同,则退出代码为0。因此,将其另存为
allequal.py
,使其可执行,您的bash代码就可以对该
grep
的结果运行
allequal.py
,并使用退出值(例如,通过
$?
)来决定是否为您打印这些结果。

我面临的问题与问题中描述的问题相同。在大型目录树中,某些文件具有相同的名称、相同的内容或不同的内容。内容不同的地方需要人们的关注,以决定如何解决每种情况下的情况。我需要创建一个这些文件的列表,以指导人们这样做

问题中的代码和abernet回复中的代码都很有用。下面是将两者结合起来的方法:将abernet响应中的python代码存储在某个文件中,例如/usr/local/bin/dou这些文件有不同的内容:

sudo tee /usr/local/bin/do_these_files_have_different_content <<EOF
#!/usr/bin/env python3
import sys

def readfile(path):
    with open(path, 'rb') as f:
        return f.read()

contents = [readfile(fname) for fname in sys.argv[1:]]
sys.exit(all(content == contents[0] for content in contents[1:]))
EOF

sudo chmod a+x /usr/local/bin/do_these_files_have_different_content
这将向stdout写入名称相同但内容不同的所有文件的路径。名称相同但内容不同的文件组用空行分隔。我将shell脚本存储在/usr/local/bin/find\u files\u中,并使用相同的\u名称\u但内容不同的\u内容调用它

find_files_with_same_name_but_different_content /path/to/my/storage/directory

比如说,当你有3个文件都命名为
spam.txt
,它们都有不同的内容时,你想删除哪两个?你是在寻找python代码来做到这一点吗?不管你想出什么规则,你显然需要一些应用该规则的代码……除非规则真的是“我不在乎,只需杀死其中两个,保留另一个”。在这种情况下,这很容易。你有一个重复文件的列表。您希望删除除一个之外的所有对象,任意选择。因此,只需从列表中弹出第一个,并删除所有剩余的。如果规则是“保留最旧的一个”,那么您首先需要将列表按时间排序(如果您只是通过
-name
进行
查找
,而不是对所有内容进行
查找
,然后对名称进行
grep
,或者只对循环中的每个文件进行
stat
并从列表中删除最旧的文件,那么这会更容易些。)谢谢你的快速评论。@abarnert,我只想列出它们并自己删除它们。Eric一切都很好。在python中使用
hashlib
不是比逐块比较更容易比较文件的方法吗?@fixxer:不太好。如果你不想读整个文件,
f.read()
甚至比使用
hashlib
所能做的任何事情都要简单。如果您想提前退出,逐块读取仍然比逐块散列简单。我想在这种情况下,您不介意浪费时间读取整个文件,但也不介意浪费RAM,散列可能比mmapping更简单,否则,当d这会使事情变得更简单吗?如果你有一个文件列表,你想将一个新文件与之匹配以测试重复的文件,那么它可能会有用吗?将一个文件与多个其他文件匹配将是浪费(不是OP要求的,而是一般要求的)@Fixxer:当然,如果你想在每次有几个新文件时一遍又一遍地重复这项工作,而不必重新读取所有旧文件,那么散列是一个很好的优化。但仍然不简单(特别是因为如果散列匹配,你仍然需要读取文件来处理冲突);这更复杂,但为了提高效率可能值得。@fixxer:但是,任何真正关心效率的人都不会在一开始就在他的树上写二次搜索。事实上,现在我想起来了,我不应该在一开始就包含逐块优化;让我重新编辑。
find_files_with_same_name_but_different_content /path/to/my/storage/directory