在一堆文件中查找共性/模式

在一堆文件中查找共性/模式

比方说,我有一个包含数百或数千个文件的文件夹,所有文件均以以下架构命名:

<random number of variable length>_<date code in YYYYMMDD format>.jpg

例子:

73923_20180927.jpg
4457582_20180927.jpg
   ...
18733557_20190401.jpg
23573_20190401.jpg
   ...

我期望 bash 脚本执行的操作是打印这些日期代码的列表,即

20180927
20190401
   ...

这听起来像是一项更容易的任务,但实际上是一项更容易的任务。由于架构始终相同,因此我已经实现了应用字符串操作,以便仅打印文件名的所需部分。但是,我仍在弄清楚如何仅打印每个日期一次。

有没有一个巧妙的方法来解决这个问题?

答案1

假设文件名全部匹配模式./*_*.jpg

for name in ./*_*.jpg; do
    name=${name##*_}              # 4457582_20180927.jpg --> 20180927.jpg
    printf '%s\n' "${name%.jpg}"  # 20180927.jpg --> 20180927
done | sort -u

这会迭代所有名称。对于每个名称,它会删除匹配的最长前缀字符串*_。然后它输出删除后缀的剩余字符串.jpg

然后对所有字符串进行排序,以便最后只输出唯一字符串的列表。

如果存在目录可能为空的风险,则应nullglob在循环 ( shopt -s nullglob) 之前设置 shell 选项。这将使循环根本不运行,而不是使用 中未扩展的通配模式运行一次$name


没有特殊原因,这是如何做到这一点的sort

declare -A skip=()

for name in ./*_*.jpg; do
    key=${name##*_}    # 4457582_20180927.jpg --> 20180927.jpg
    key=${key%.jpg}    # 20180927.jpg --> 20180927
    if [[ ! -v skip[$key] ]]; then
        printf '%s\n' "$key"
        skip[$key]=1
    fi
done

在这里,我跟踪哪些字符串已作为关联数组 中的键输出skip。如果字符串对应于数组中的某个键,则不会输出该字符串。

答案2

假设确实没有不正确的文件名,则在该目录中运行:

ls -U | awk '-F[_.]' '{ print $2 }' | sort | uniq

相关内容