假设我有以下目录结构:
root
|-- dirA
|-- file.jpg
|-- file-001.jpg <-- dup
|-- file2.jpg
|-- file3.jpg
|-- dirB
|-- fileA.jpg
|-- fileA_ios.jpg <-- dup
|-- fileB.jpg
|-- fileC.jpg
|-- dirC
|-- fileX.jpg
|-- fileX_ios.jpg <-- dup
|-- fileX-001.jpg <-- dup
|-- fileY.jpg
|-- fileZ.jpg
因此,给定一个根文件夹,如何递归地找到具有相同名称(仅后缀不同)的重复项?
名称可以是任何字符串,但不一定是file...
.后缀可以是 001、002、003 等。但可以安全地假设将有一个 3 位数字模式和_ios
字面意义(用于正则表达式匹配)。
我的linux foo 不是很好。
答案1
它有点长,但它是一个命令行。它查看文件的内容并使用加密哈希 ( md5sum
) 进行比较。
find . -type f -exec md5sum {} + | sort | sed 's/ */!/1' | awk -F\| 'BEGIN{first=1}{if($1==lastid){if(first){first=0;print lastid, lastfile}print$1, $2} else first=1; lastid=$1;lastfile=$2}'
正如我所说,这有点长......
find
针对md5sum
当前目录树中的所有文件运行。然后输出是sort
通过 md5 哈希进行的。由于文件名中可能存在空格,因此sed
将第一个字段分隔符(两个空格)更改为垂直管道(不太可能出现在文件名中)。
最后一个awk
命令跟踪三个变量:lastid
= 前一个条目的 md5 哈希值,lastfile
= 前一个条目的文件名,以及first
= 第一次看到的lastid。
输出包括哈希值,因此您可以看到哪些文件彼此重复。
这并不表明文件是否是硬链接(相同的 inode,不同的名称);它只会比较内容。
更新:仅根据文件的基本名称进行更正。
find . -type f -print | sed 's!.*/\(.*\)\.[^.]*$!\1|&!' | awk -F\| '{i=indices[$1]++;found[$1,i]=$2}END{for(bname in indices){if(indices[bname]>1){for(i=0;i<indices[bname];i++){print found[bname,i]}}}}'
这里,find
仅列出文件名,sed
采用路径名的基本名称部分,并创建一个包含基本名称和完整路径名的两个字段表。然后awk
创建一个所见路径名的表(“找到”),按基本名称和项目编号进行索引; “indices”数组跟踪有多少个基本名称已被看到。然后“END”子句打印出找到的任何重复的基本名称。
答案2
您可能需要考虑专门用于搜索重复文件的程序,而不是依赖于名称,例如fdupes
或fslint
。
答案3
创建目录结构
mkdir dir{A,B,C}
touch dirA/file{,-001,2,3}.jpg
touch dirB/file{A,A_ios,B,C}.jpg
touch dirC/file{X,X_ios,X-001,Y,Z}.jpg
显示多个重复文件
find . -name '*.jpg' -type f |sed 's/\(.*\/\(file.\).*\(.jpg\)\)/\2/' |sort |uniq -c|grep -v 1
退货
2 文件A
3 文件X