我有包含许多文件的文件夹,这些文件均以日期开头 - 例如 20200403。我想查找哪些文件夹有多个具有相同日期的文件,即前 8 个字母相同。只有在每个特定文件夹中,日期才重要。跨文件夹没关系。
文件元数据不一定符合文件名日期,因此我无法使用它作为查找它们的方法。
答案1
您可以考虑通过 传递一个(适当排序的)文件名列表uniq -d
。uniq
例如,假设您的 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
如果您需要处理包含换行符和支持空分隔符的文件名cut
,uniq
您可以将管道更改为
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 分隔的记录流通过管道传输。对于每条记录,仅保留最后一个组成部分(文件名)的前八个字符,并将生成的路径存储在关联数组中。当找到重复项时,将打印目录部分(即删除文件名部分的路径)。