递归搜索重复相同前 8 个字母的文件

递归搜索重复相同前 8 个字母的文件

我有包含许多文件的文件夹,这些文件均以日期开头 - 例如 20200403。我想查找哪些文件夹有多个具有相同日期的文件,即前 8 个字母相同。只有在每个特定文件夹中,日期才重要。跨文件夹没关系。

文件元数据不一定符合文件名日期,因此我无法使用它作为查找它们的方法。

答案1

您可以考虑通过 传递一个(适当排序的)文件名列表uniq -duniq例如,假设您的 shell对排序规则有相同的想法

printf -- "%s\n" * | cut -c1-8 | uniq -d

如果结果非空,则一定有重复项。将其包装在find命令中:

find . -type d -exec sh -c '
  cd "$1" && test -n "$(printf -- "%s\n" * | cut -c1-8 | uniq -d)"
' find-sh {} \; -print

所以给出

$ tree .
.
├── subdir1
│   └── 20200403foo
├── subdir2
│   ├── 20200403bar
│   └── 20200403foo
├── subdir3
│   └── 20200403foo
├── subdir4
│   ├── 20200403bar
│   └── 20200403foo
└── subdir5
    └── 20200403foo

5 directories, 7 files

然后

$ find . -type d -exec sh -c 'cd "$1" && test -n "$(printf -- "%s\n" * | cut -c1-8 | uniq -d)"' find-sh {} \; -print
./subdir4
./subdir2

如果您需要处理包含换行符和支持空分隔符的文件名cutuniq您可以将管道更改为

printf "./%s\0" * | cut -zc1-10 | uniq -zd

答案2

一种便携式解决方案,还可以正确处理任意文件路径,包括包含换行符的文件路径,但代价是一定程度的不优雅和缓慢:

find /path/to/dir -type d \( -exec sh -c '
  cd "$1"
  printf "%s/" [0123456789][0123456789][0123456789][0123456789][01][0123456789][0123][0123456789]* \
    | awk -v RS="/" "seen[substr(\$0,1,8)]++ { exit 1 }"
  ' mysh {} \; -o -print \)

find用于递归地搜索目录,/path/to/dir并在每个找到的目录中执行一个脚本,该脚本通过管道传输与大致类似于日期的模式匹配的文件名(假定为 yyyy/mm/dd 格式),每个脚本都以 ,/结尾awk读取分隔记录的实例,一旦在输入中找到重复的八字符(从第一个字符开始)字符串,就会/以状态退出,从而导致目录名称被编辑。1-print

基于 GNU 工具的更快替代方案:

find /path/to/dir -type f -name '[0123456789][0123456789][0123456789][0123456789][01][0123456789][0123][0123456789]*' \
  -print0 | awk -v FS='/' -v OFS='/' -v RS='\0' '
  { file=substr($NF,1,8); $NF=""; dir=$0 }
  seen[dir file]++ { dupl[dir] }
  END { for (d in dupl) print d }'

在这里,只有名称(大致)以日期开头的常规文件才会在/path/to/dir.找到的文件路径awk作为 NUL 分隔的记录流通过管道传输。对于每条记录,仅保留最后一个组成部分(文件名)的前八个字符,并将生成的路径存储在关联数组中。当找到重复项时,将打印目录部分(即删除文件名部分的路径)。

相关内容