Найти общность/образец в куче файлов

Найти общность/образец в куче файлов

Допустим, у меня есть папка с сотнями или тысячами файлов, все из которых названы по следующей схеме:

<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). Это заставит цикл вообще не запускаться вместо того, чтобы запуститься один раз с нераскрытым шаблоном подстановки в $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

Связанный контент