Como encontro o timestamp mais recente em nomes de diretório em um script bash?

3

Eu tenho alguns diretórios timestampedidos nomeados com um prefixo que pode variar, e o timestamp no formato acessível YYYYMMDD, seguido por sufixos variados que também denotam ordem cronológica (não da maneira mais sã). Infelizmente, a parte do título do nome pode incluir o caractere _ , que é usado como o delimitador de campo.

Por exemplo:

/collect/mydir_20161102_0A
/collect/mydir_20161102_0B
/collect/mydir_20161102_0C
/collect/mydir_20161102_1
/collect/mydir_20161102_2
/collect/other_dir_20161103_0A
/collect/other_dir_20161103_0B
/collect/mydir_20161104_0A
/collect/mydir_20161104_0B
/collect/mydir_20161104_0C
/collect/mydir_20161104_1
/collect/mydir_20161104_2

A ordem dos nomes mostrados aqui é realmente a ordem cronológica de criação, incluindo os sufixos, de modo que 0A vem antes de 0B, e todos os 0s vêm antes de 1. Não deve haver qualquer incidência de prefixo de título diferente com o mesmo timestamp.

Os diretórios podem ter sido alterados ou modificados desde a criação, portanto, o uso de ctime e mtime estão fora.

Eu preciso mostrar a string contendo o título e o timestamp, com ou sem o caminho anterior, então mydir_20161104 ou /collect/mydir_20161104 , mas isso sempre deve vir do diretório mais recente. A pesquisa não deve recorrer pelos níveis de diretório.

Gostaria de evitar a análise de ls também!

    
por Arronical 04.11.2016 / 16:11

1 resposta

3

Pode não ser bonito e não estou a lidar com nomes de ficheiros com novas linhas:

find collect/ -mindepth 1 | 
  awk -F_ '{print $(NF-1),$NF,$0}' | 
  sort -V | 
  sed -r 's/^([^ ]* ){2}//'

Então:

  1. Listando os arquivos com find
  2. Adicionando os últimos 2 _ -delimited campos no nome do arquivo ao início dele usando awk
  3. Classificando-o ( -V - classificação de versão - pode manipular campos como 0A e 1 )
  4. Removendo a parte adicionada com sed

Poderia ser seguro para nomes de arquivos contendo qualquer caractere válido, mas eu teria que substituir awk por sed para isso.

Minha saída:

$ find collect/ -mindepth 1 | awk -F_ '{print $(NF-1),$NF,$0}' | sort -V | sed -r 's/^([^ ]* ){2}//'    
collect/mydir_20161102_0A
collect/mydir_20161102_0B
collect/mydir_20161102_0C
collect/mydir_20161102_1
collect/mydir_20161102_2
collect/other_dir_20161103_0A
collect/other_dir_20161103_0B
collect/mydir_20161104_0A
collect/mydir_20161104_0B
collect/mydir_20161104_0C
collect/mydir_20161104_1
collect/mydir_20161104_2

Claro, isso é apenas analisar ls . ;)

Se você precisar apenas do título e do timestamp sem o sufixo, inverta a classificação ( sort -Vr ) e modifique o último sed para:

sed -r 's:.*/::;s/_[^_]*$//;q'

Então:

$ find collect/ -mindepth 1 | awk -F_ '{print $(NF-1),$NF,$0}' | sort -rV | sed -r 's:.*/::;s/_[^_]*$//;q'
mydir_20161104

E uma versão que pode manipular nomes de arquivos com novas linhas:

find collect/ -mindepth 1 -print0 | sed -rz 's/(.*)(_[^_]*)(_[^_]*)$/ &/' | sort -zrV | sed -zr 's:.*/::;s/_[^_]*$//;q'

Isso usa as linhas -print0 -delimited por todo o texto ( find in -z , sed in sort e awk ). sed é substituído por um comando %code% equivalente.

    
por muru 04.11.2016 / 16:41