Encontre pontos em comum/padrão em vários arquivos

Encontre pontos em comum/padrão em vários arquivos

Digamos que eu tenha uma pasta com centenas ou milhares de arquivos, todos nomeados de acordo com o seguinte esquema:

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

Exemplo:

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

O que espero que meu script bash faça é imprimir uma lista desses códigos de data, ou seja

20180927
20190401
   ...

Parece uma tarefa mais fácil do que é. Como o esquema é sempre o mesmo, já consegui aplicar a manipulação de strings para imprimir apenas a parte necessária dos nomes dos arquivos. No entanto, ainda estou descobrindo como imprimir cada data apenas uma vez.

Existe uma maneira legal de sair disso?

Responder1

Supondo que todos os nomes de arquivos correspondam ao padrão ./*_*.jpg:

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

Isso itera sobre todos os nomes. Para cada nome, ele remove a string de prefixo mais longa correspondente *_. Em seguida, ele gera a string restante com o .jpgsufixo removido.

Todas as strings são então classificadas de forma que apenas uma lista de strings exclusivas seja exibida no final.

Se houver risco de o diretório estar vazio, você deve definir a nullglobopção shell antes do loop ( shopt -s nullglob). Isso faria com que o loop não fosse executado, em vez de ser executado uma vez com o padrão globbing não expandido em $name.


Sem nenhuma razão específica, é assim que se faz sem 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

Aqui, acompanho quais strings já foram geradas como chaves em uma matriz associativa, skip. Uma string não será gerada se corresponder a uma chave no array.

Responder2

Supondo que realmente não haja nomes de arquivos impróprios, execute nesse diretório:

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

informação relacionada