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

查找并删除目录层次结构中的重复文件名
#!/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

答案1

如果将输出放入循环find中,while read则可以逐行处理它们:

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

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

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

编辑: test(与 相同[)没有==运算符,您只需要=

答案2

我刚刚在旧的 bash 历史记录中发现了这个“宝石”,它实际上可以正常工作,而不会在文件名中遇到空格。

内容比较

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,对此输出进行排序(格式:哈希文件名),抓取哈希列,将其减少为双倍的值。(意味着有重复)
  • 第二行:对于每个重复出现的哈希值,再次遍历并打印文件名,如果当前文件具有当前哈希值(意味着该文件是多个文件之一)

示例输出:

./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;

更新:不幸的是,此版本再次因文件名中的空格而出现问题。

答案3

问题就出在这行代码上for FILE in $FILES; do- for 循环根据空格分隔符分配 FILE 变量。因此,如果文件有一个或多个空格,它将无法工作。只需将默认 IFS 从空格更改为新行或制表符即可。如果我没记错的话,你可以在 bash 中使用类似这样的代码设置 IFS -

IFS=$'\n'

相关内容