Estou procurando um liner de shell para encontrar o arquivo mais antigo em uma árvore de diretórios.
72
Isso funciona (atualizado para incorporar a sugestão de Daniel Andersson):
find -type f -printf '%T+ %p\n' | sort | head -n 1
find -type f -printf '%T+ %p\n' | sort | head -1
find
está vazia devido ao fato de eu ter o nome do arquivo que contém uma nova linha.Este é um pouco mais portátil e, como não depende da
find
extensão GNU-printf
, também funciona no BSD / OS X:A única desvantagem aqui é que é um pouco limitado ao tamanho de
ARG_MAX
(o que deve ser irrelevante para a maioria dos kernels mais recentes). Portanto, se houver mais degetconf ARG_MAX
caracteres retornados (262.144 no meu sistema), ele não fornecerá o resultado correto. Também não é compatível com POSIX, porque-print0
exargs -0
não é.Aqui estão descritas mais algumas soluções para esse problema: Como posso encontrar o arquivo mais recente (mais recente, antigo e antigo) em um diretório? - Wiki de Greg
fonte
xargs: ls: terminated by signal 13
erro como efeito colateral. Eu estou supondo que é SIGPIPE. Não sei por que não recebo um erro semelhante quando canalizo a saída da classificação para iniciar minha solução.head
comando que sai quando lê uma linha e, portanto, "quebra" o pipe, eu acho. Você não recebe o erro porquesort
parece não reclamar, masls
ocorre no outro caso.xargs
precisam ser chamadosls
mais de uma vez. Nesse caso, as saídas classificadas dessas múltiplas invocações acabam concatenadas quando devem ser mescladas.ls
ele e globo ocular o arquivo mais antigo, a sua solução provavelmente será superado o limite de comprimento de linha de comando, fazendo com quels
a ser invocada várias vezes. Você receberá a resposta errada, mas nunca saberá.É garantido que os seguintes comandos de comandos funcionam com qualquer tipo de nome de arquivo estranho:
O uso de um byte nulo (
\0
) em vez de um caractere de avanço de linha (\n
) garante que a saída de localização ainda seja compreensível caso um dos nomes de arquivo contenha um caractere de avanço de linha.A
-z
opção faz com que a classificação e o grep interpretem apenas bytes nulos como caracteres de final de linha. Como não existe essa opção de cabeçalho, usamos emgrep -m 1
vez disso (apenas uma ocorrência).Os comandos são ordenados pelo tempo de execução (medido na minha máquina).
O primeiro comando será o mais lento, pois ele deve converter o mtime de todos os arquivos em um formato legível por humanos primeiro e depois classificar essas strings. Tubulação para gato evita colorir a saída.
O segundo comando é um pouco mais rápido. Enquanto ele ainda realiza a conversão da data, classificar numericamente (
sort -n
) os segundos decorridos desde a época do Unix é um pouco mais rápido. sed exclui os segundos desde a época do Unix.O último comando não faz nenhuma conversão e deve ser significativamente mais rápido que os dois primeiros. O próprio comando find não exibirá o mtime do arquivo mais antigo, portanto, o stat é necessário.
Páginas de manual relacionadas: find - grep - sed - sort - stat
fonte
Embora a resposta aceita e outras pessoas aqui façam o trabalho, se você tiver uma árvore muito grande, todas elas classificarão todo o conjunto de arquivos.
Melhor seria se pudéssemos listá-las e acompanhar as mais antigas, sem a necessidade de classificar.
É por isso que eu vim com essa solução alternativa:
Espero que possa ajudar, mesmo que a pergunta seja um pouco antiga.
Editar 1: essas alterações permitem analisar arquivos e diretórios com espaços. É rápido o suficiente para emiti-lo na raiz
/
e encontrar o arquivo mais antigo de todos os tempos.Comando explicado:
Executando:
EDIT 2: Mesmo conceito, melhor solução usando
find
para observar o tempo de acesso (use%T
com o primeiroprintf
para tempo de modificação ou%C
para alteração de status ).EDIT 3: O comando abaixo usa o tempo de modificação e também imprime o progresso incremental à medida que localiza arquivos mais antigos e mais antigos, o que é útil quando você tem alguns registros de data e hora incorretos (como 1970-01-01):
fonte
ls
é ruim para scripts, pois sua saída não se destina a máquinas, a formatação da saída varia entre as implementações. Como você já declarou,find
é bom para scripts, mas também pode ser bom adicionar essas informações antes de falar sobre asls
soluções.Por favor, use ls - a página de manual informa como solicitar o diretório.
O -n 2 é para que você não obtenha o "total" na saída. Se você deseja apenas o nome do arquivo.
E se você precisar da lista na ordem normal (obtendo o arquivo mais recente)
Muito mais fácil do que usar find, muito mais rápido e mais robusto - não precisa se preocupar com os formatos de nomeação de arquivos. Também deve funcionar em quase todos os sistemas.
fonte
fonte
sort -n
.Parece que por "mais antigo" a maioria das pessoas assumiu que você quis dizer "tempo de modificação mais antigo". Provavelmente isso foi corrigido, de acordo com a interpretação mais rigorosa de "mais antigo", mas, caso você desejasse aquele com o tempo de acesso mais antigo , modificaria a melhor resposta da seguinte maneira:
Observe o
%A+
.fonte
find ./search/dirname -type f -printf '%T+ %h/%f\n'
imprime datas e nomes de arquivos em duas colunas.sort | head -n1
mantém a linha correspondente ao arquivo mais antigo.echo $2
exibe a segunda coluna, ou seja, o nome do arquivo.fonte