Encontre arquivos na ordem do carimbo de data/hora

Encontre arquivos na ordem do carimbo de data/hora

dirtem dois arquivos regulares.

file1tem abc\n, file2tem def\n. Compacte esses dois arquivos com gzip, conforme mostrado abaixo,

#ls
#echo 'abc\n' > file1
#echo 'def\n' > file2
#gzip file1
#gzip file2
#ls
file1.gz  file2.gz

Depois de analisar o conteúdo,

#find . -type f  -name "*.gz" -exec zgrep -Iq . \{} \; -exec zcat \{} \;
def\n
abc\n

Não obtenho o conteúdo dos arquivos na ordem do horário de criação do arquivo. A saída esperada deve ser sempre abc\ndef\n.

Observação interessante: a produção real é às vezes, def\nabc\ne às vezesabc\ndef\n

Pergunta:

Como encontrar arquivos em ordem (decrescente/aumentante) de carimbo de data/hora?

Responder1

A ordem dos arquivos informada por findé opaca para o usuário. Pode ser a ordem em que aparecem no diretório. Algumas findimplementações os reordenam por número de inode ou outros critérios na tentativa de melhorar o desempenho. A única maneira de alterar a ordem é através do -depthpredicado que informa findpara processar/saída de folhas antes do branch em que estão.

Como alternativa find, você pode usar zsho recurso glob recursivo de:

zgrep whatever ./**/*.gz(D.Om)

O Omqualificador glob deve classificar pela hora da última modificação (o mais antigo primeiro). .é apenas para arquivos regulares (equivalente a find's -type f), Dé incluir arquivos ocultos (ponto), como findfaria por padrão.

Se você conseguir umlista de argumentos muito longaerro, você pode usar zargs:

autoload -U zargs # best in ~/.zshrc
zargs ./**/*.gz(D.Om) -- zgrep whatever

Com bash(ou qualquer shell que suporte substituição de processo no estilo Ksh) e ferramentas GNU recentes, um equivalente seria:

xargs -r0a <(
  export LC_ALL=C
  find . -type f -name '*.gz' -printf '%T@\t%p\0' |
    sort -zn | cut -zf2-) zgrep whatever

Responder2

Uma opção é gerar o carimbo de data/hora do arquivo junto com o caminho do arquivo, classificá-lo e removê-lo:

find -type f -name "*.gz" -printf '%C@\t%p\n'|sort -nk1|cut -f2-|xargs zcat 

Observe que se seus nomes de arquivos puderem conter caracteres potencialmente inseguros (como espaços), basta substituir

xargs zcat 

com

xargs -d "\n" zcat 

e se precisar acomodar as novas linhas nos nomes dos arquivos, você pode usar um byte nulo para encerrar os registros, conforme detalhado na resposta do @stéphane-chazelas (isso raramente é um problema na prática).

Responder3

Infelizmente, o comando find funciona de tal forma que não é garantido que a saída esteja em ordem alfabética ou de idade do arquivo. Você pode tentar algo como:

ls -1dtr $(find . -maxdepth 1 -type f -name '*.gz') | xargs gzcat $1

informação relacionada