Encontre o arquivo mais recente por data de modificação

29

Se eu quiser encontrar o arquivo mais recente (mtime) em um diretório (grande) contendo subdiretórios, como eu o faria?

Várias postagens que eu encontrei sugerem alguma variação de ls -lt | head (divertidamente, muitos sugerem ls -ltr | tail , que é o mesmo, mas menos eficiente), o que é bom, a menos que você tenha subdiretórios (eu faço).

Então, novamente, você poderia

find . -type f -exec ls -lt \{\} \+ | head

que definitivamente fará o truque para quantos arquivos forem especificados por um comando, ou seja, se você tiver um diretório grande , -exec...\+ emitirá comandos separados; portanto, cada grupo será classificado por ls dentro de si, mas não acima do conjunto total; a cabeça, portanto, pegará a última entrada do primeiro lote.

Alguma resposta?

    
por Rich 13.09.2011 / 11:22

6 respostas

38

Você não precisa recorrer a comandos externos (como ls ) porque find pode fazer tudo que precisa por meio da ação -printf :

find /path -printf '%T+ %p\n' | sort -r | head
    
por enzotib 13.09.2011 / 11:29
7

Eu tive um problema semelhante hoje, mas o ataquei sem find . Eu precisava de algo curto Eu poderia atropelar ssh para retornar o arquivo editado mais recentemente no meu diretório home. Isso é basicamente o que eu criei:

ls -tp | grep -v /$ | head -1

A opção -p para ls adiciona uma barra à diretórios, o grep -v remove as linhas que terminam em uma barra (aka, todos os diretórios) e o head -1 limita a saída a um único arquivo. / p>

Isso é muito menos detalhado do que usar find se tudo que você deseja retornar é o nome do arquivo.

    
por Pat Regan 10.01.2013 / 17:42
3

Isso está no meu sistema mais rápido que printf , embora eu não entenda por que

find /path -type f -exec stat -c "%y %n" {} + | sort -r | head
    
por arrange 13.09.2011 / 11:46
1

Não é quase tão na moda, mas também é possível conseguir isso com o Midnight Commander : procure por *, panelize o resultado, classifique por tempo de modificação na ordem inversa.

Obviamente, é um pouco mais lento que find - meu diretório inicial, contendo 922000 arquivos, foi classificado por mc em quase 14 minutos enquanto find gastou menos de 5 - mas há alguns benefícios:

  • Eu provavelmente gastaria mais do que a diferença de 9 minutos inventando uma invocação de busca adequada:)

  • menos chance de erro (esqueci de especificar -r para ordenar etc. - começar de novo)

  • é possível jogar com o conjunto de resultados alterando a ordem de classificação, etc. - sem reexaminar os arquivos.

  • possível executar operações de arquivo apenas em alguns arquivos do conjunto de resultados - ou seja, classificar por tamanho, excluir alguns arquivos grandes que não são necessários

por Sergey 13.09.2011 / 13:25
1

EDIT: Eu acho que este post não é "não particularmente útil", como eu pensava que era. Esta é uma solução muito rápida que apenas acompanha o arquivo modificado mais recentemente (em vez de classificar toda a lista de arquivos):

find . -type f -printf '%T@ %p\n' | awk 'BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; } { if ($1 > mostrecenttime) { mostrecenttime = $1; mostrecentline = $0; } } END { print mostrecentline; }' | cut -f2- -d ' '

Espalhe várias linhas para maior clareza:

find . -type f -printf '%T@ %p\n' | awk '
    BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; }
    {
        if ($1 > mostrecenttime)
            { mostrecenttime = $1; mostrecentline = $0; }
    }
    END { print mostrecentline; }' | cut -f2- -d ' '

Fim do EDIT

Não é um post particularmente útil, mas como 'organize' estava discutindo a velocidade, pensei em compartilhar isso.

As soluções do array e da enzotib envolvem a listagem de todos os arquivos dentro do diretório com seus mtimes e, em seguida, a classificação. Como você sabe, a classificação não é necessária para encontrar o máximo. Encontrar o máximo pode ser feito em tempo linear, mas a ordenação leva n log (n) tempo [Eu sei que a diferença não é muito, mas ainda;)]. Não consigo pensar em uma maneira legal de implementar isso. [EDIT: Uma implementação simples (embora de aparência suja) e rápida fornecida acima.]

Próxima melhor coisa - Para encontrar o arquivo editado mais recentemente em um diretório, localize recursivamente o arquivo editado mais recentemente em cada subdiretório de nível 1. Deixe este arquivo representar o subdiretório. Agora, classifique os arquivos de nível 1 junto com os representantes dos subdiretórios de nível 1. Se o número do número de arquivos e subdiretórios de nível 1 de cada diretório for quase uma constante, esse processo deverá ser dimensionado linearmente com o número total de arquivos.

Isso é o que eu criei para implementar isso:

findrecent() { { find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1; }
findrecent .

Eu corri isso e recebi um monte de erros find: findrecent: No such file or directory . Razão: -exec de find é executado em um shell diferente. Eu tentei definir findrecent em .bashrc, .xsessionrc mas estes não ajudaram [eu apreciaria a ajuda aqui]. No final, eu recorri a colocar

#!/bin/bash
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;

em um script chamado findrecent no meu PATH e depois executá-lo.

Eu corri isso, fiquei esperando e esperando sem saída. Só para ter certeza de que não estava lidando com nenhum loop infinito, modifiquei o arquivo para

#!/bin/bash
echo "$1" >&2
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;

e tentei novamente. Ele funcionou - mas demorou 1 minuto e 35 segundos em minha casa - as soluções do arranjo e da enzotib levaram 1,69, 1,95 segundo, respectivamente!

Tanto para a superioridade de O (n) sobre O (n log (n))! Porra você chama a função de sobrecarga! [Ou melhor, sobrecarga de chamada de script]

Mas esse script é dimensionado melhor que as soluções anteriores e aposto que ele será executado com mais rapidez do que no banco de memória do Google; D

    
por S Prasanth 11.12.2012 / 13:51
1

Use perl no conjonctin com find :

 find my_directory -type f -printf '%T@\t%p\n' | perl -ane '@m=@F if ($F[0]>$m[0]); END{print $m[1];}'

Você obtém o nome do arquivo com o maior epoch == último arquivo modificado.

    
por MUY Belgium 10.03.2015 / 12:08