查找并删除目录层次结构中的重复文件名

#!/bin/sh LASTBASE="" find $1 -type f -print | rev | sort | rev | while read FILE do BASE=$(basename "$FILE") if [ "$BASE" = "$LASTBASE" ]; then rm "$FILE" LASTBASE="$BASE" done 

如果你把find的输出放到while read循环中,你可以逐行处理它们:

 find nnn/ -type f -print | rev | sort | rev | while read FILE; do ... done 

编辑 :因此,如果文件名包含双(连续)空格,则此方法会中断,因为read实际上是根据$IFS分割该行,然后在存储最后一个variables时再次将其连接。 要解决这个问题,你可以暂时改变$IFS以禁用拆分:

 OIFS="$IFS" IFS="" find | while read... IFS="$OIFS" 

编辑test (这是一样的[ )没有==运算符,你只是想=

我刚刚在一个古老的bash历史中发现了这个“gem”,实际上它并没有在文件名中的空白处绊倒。

内容明智的比较

 for hash in `find . -exec md5sum {} \; 2>/dev/null | sort | awk '{ print $1 }' | uniq -d`; do find . -exec md5sum {} \; 2>/dev/null | grep $hash | awk '{print $2 }'; done; 

非正式:

  • 第一行:遍历目录树并计算下面所有文件的md5sum,对这个输出进行sorting(格式:hash filename),抓取哈希列,将其减less一倍。 (意味着重复)
  • 第二行:对于每一个双重散列哈希,如果当前文件具有当前散列,则再遍历并打印文件名(表示文件是多个文件之一)

示例输出:

 ./aFile ./aFolder/aFile ./1000digitsOfPI ./a/b/c/thousanddigitsofPI ./b File ./bFolder/cFolder/b File 

删除不在这里实现,因为它可能很难决定要保留的加倍文件的哪个版本。


文件名比较

如果您只想查看文件名而不是查看内容,则更容易:

 for name in `find . -type f -printf "%f\n" | sort | uniq -d`; do find . -name $name; done; 

更新:不幸的是,这个版本再次打破文件名中的空格。

问题出for FILE in $FILES; do这一行代码for FILE in $FILES; do for FILE in $FILES; do – for循环根据空格分隔符来分配FILEvariables。 所以如果一个文件有一个或多个空格,那么它将不起作用。 只需将默认的IFS从空间更改为新的行或选项卡。 如果我没有记错的话,你可以用bash来设置IFS,

IFS = $ '\ n'