Questão Unix / Linux encontrar e classificar por data modificada


Como posso fazer uma simples find qual ordenaria os resultados modificados mais recentemente?

Aqui é a corrente find Estou usando (estou fazendo um shell escape no PHP, então esse é o raciocínio para as variáveis):

find '$dir' -name '$str'\* -print | head -10

Como eu poderia ter este pedido a pesquisa modificada mais recentemente? (Nota Eu não quero que ele classifique 'depois' da pesquisa, mas sim encontre os resultados baseados no que foi modificado mais recentemente.)


103


origem


github.com/shadkam/recentmost faria o que é desejado - mas é preciso construí-lo - user3392225


Respostas:


Usa isto:

find . -printf "%T@ %Tc %p\n" | sort -n

printf argumentos de man find:

  • %Tk: Hora da última modificação do arquivo no formato especificado por k.

  • @: segundos desde 1º de janeiro de 1970, 00:00 GMT, com parte fracionária.

  • c: data e hora do local (Sat Nov 04 12:02:33 EST 1989).

  • %p: Nome do arquivo.


103



+ 1 Muito útil, a primeira resposta para isso eu encontrei com uma saída de data legível / útil - Jake N
mais confiável (e muito simples) já que o tempo é concedido para ser numericamente sequencial (portanto sempre sempre ordenável), thx! - Aquarius Power
Eu tenho esse alias para encontrar arquivos recentes no meu ~/.zshrc: fr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY %Tk:%TM %p\n" | sort -n | cut -d " " -f 2- | grep -i "$@" ; } Ele recursivamente localiza todos os arquivos contendo o padrão do primeiro argumento passado para o comando (fr <pattern>) e os classifica com o último mais recente. - Joel Ostblom
Para ISO 8601 data de saída, use find . -printf "%T@ %CY-%Cm-%CdT%CH:%CM:%CS %p\n" | sort -n. Como classifica naturalmente, também pode ser usado diretamente no tipo: find . -printf "%CY-%Cm-%CdT%CH:%CM:%CS %p\n" | sort -n - Peter Mortensen


O método mais fácil é usar o zsh, graças ao seu Qualificadores glob.

print -lr -- $dir/**/$str*(om[1,10])

Se você tiver o GNU find, faça com que ele imprima os tempos de modificação do arquivo e ordene por isso.

find -type f -printf '%T@ %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\n' | head -n 10

Se você tiver o GNU, mas não outros utilitários GNU, use novas linhas como separadores ao invés de nulos; você perderá o suporte para nomes de arquivos contendo novas linhas.

find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^ ]* //' | head -n 10

Se você tem Perl (aqui eu assumirei que não há novas linhas em nomes de arquivos):

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        @sorted = sort {$_{$a} <=> $_{$b}} keys %_;  # sort by increasing age
        print @sorted[0..9];
    }'

Se você tem Python (também assumindo que não há novas linhas em nomes de arquivos):

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in (sorted(times.iterkeys(), key=lambda f:times[f], reverse=True))[:10]: print f'

Há provavelmente uma maneira de fazer o mesmo no PHP, mas eu não sei disso.

Se você quer trabalhar apenas com ferramentas POSIX, é um pouco mais complicado; Vejo Como listar arquivos classificados por data de modificação recursivamente (nenhum comando stat disponível!) (retatinar os primeiros 10 é a parte fácil).


80



Eu acho que o find versão mostra os arquivos mais antigos, e que você precisa adicionar o -r opção para sort. - Quentin Pradet
Meu sed diz que não tem uma opção -z. - Kef Schecter
@KefSchecter Em seguida, use novas linhas como separadores, mas você perderá o suporte para novas linhas em nomes de arquivos. - Gilles
O acima é para python2. Se você só tem python3, algumas pequenas mudanças: python3 -c 'import os, sys; times = {} para f em sys.stdin.readlines (): f = f [0: -1]; times [f] = os.stat (f) .st_mtime para f in (classificado (times.keys (), key = lambda f: times [f], reverso = True)) [: 10]: print (f); ' - Neil McGill


Você não precisa PHP ou Python, apenas ls:

man ls:
-t     sort by modification time
-r,    reverse order while sorting (--reverse )
-1     list one file per line

find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;

Se o comando * sair com um status de falha (isto é, Lista de argumentos muito longa), então você pode iterar com o find. Parafraseado de: O comprimento máximo de argumentos para um novo processo

  • find . -print0|xargs -0 command      (otimiza velocidade, se achado não implementa "-exec +" mas sabe "-print0")
  • find . -print|xargs command     (se não houver espaço em branco nos argumentos)

Se a maior parte dos argumentos consistir em caminhos longos, absolutos ou relativos, tente mover suas ações para o diretório: cd /directory/with/long/path; command * E outra correção rápida pode ser corresponder a menos argumentos: command [a-e]*; command [f-m]*; ... 


31



Se houver muitos arquivos, isso falhará com 'Argument list too long' no ls. - occulus
Isso é verdade, mas acredito que a pergunta foi "como faço para encontrar um simples ..." - Ярослав Рахматуллин
ls não cita nomes de arquivos de uma maneira que os xargs possam entender (nenhuma opção -0 e os vários estilos de aspas são inadequados) - Tobu


Você só precisa ls

Você poderia fazer find /wherever/your/files/hide -type f -exec ls -1rt "{}" +; como dito acima,

ou

ls -1rt `find /wherever/your/file/hides -type f`

10



Se houver muitos arquivos, isso falhará com 'Argument list too long' no ls. Talvez recook para usar xargs? - occulus
Mas se xargs chamadas ls várias vezes, o tipo será quebrado. - Aaron D. Marasco
Isso falha para arquivos com espaços em seus nomes. Algum conselho? - user74094


Estendendo Resposta de user195696:

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

Para cada arquivo, este primeiro gera o registro de data e hora numérico (para classificação por, seguido por tabulação \t), então um timestamp legível, então o tamanho do arquivo (infelizmente find's -printf não pode fazer em mebibytes, apenas kibibytes), então o nome do arquivo com o caminho relativo.

Então sort -n classifica-o pelo primeiro campo numérico.

Então cut se livrar desse primeiro campo numérico que não é de interesse para o usuário. (Imprime o segundo campo em diante.) O separador de campo padrão é \t ou tabulação.

Exemplo de saída:

Thu 06 Feb 2014 04:49:14 PM EST     64 KiB ./057_h2_f7_10/h2_f7_10.class
Fri 07 Feb 2014 02:08:30 AM EST 7962976 KiB ./056_h2_f7_400/h2__rh_4e-4.mph
Fri 07 Feb 2014 02:23:24 AM EST 7962976 KiB ./056_h2_f7_400/h2_f7_400_out_Model.mph
Fri 07 Feb 2014 02:23:24 AM EST      0 KiB ./056_h2_f7_400/h2_f7_400_out.mph.status
Fri 07 Feb 2014 02:23:24 AM EST     64 KiB ./056_h2_f7_400/1579678.out
Fri 07 Feb 2014 03:47:31 AM EST 8132224 KiB ./057_h2_f7_10/h2__rh_1e-5.mph
Fri 07 Feb 2014 04:00:49 AM EST 8132224 KiB ./057_h2_f7_10/h2_f7_10_out_Model.mph
Fri 07 Feb 2014 04:00:49 AM EST      0 KiB ./057_h2_f7_10/h2_f7_10_out.mph.status
Fri 07 Feb 2014 04:00:49 AM EST     64 KiB ./057_h2_f7_10/1579679.out
Fri 07 Feb 2014 09:47:18 AM EST   9280 KiB ./056_h2_f7_400/h2__rh_4e-4.mat
Fri 07 Feb 2014 10:51:23 AM EST   9728 KiB ./018_bidomain/h2_plain__rh_1e-5.mat
Fri 07 Feb 2014 10:58:33 AM EST   9568 KiB ./057_h2_f7_10/h2__rh_1e-5.mat
Fri 07 Feb 2014 05:05:38 PM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.java
Fri 07 Feb 2014 06:06:29 PM EST     32 KiB ./058_h2_f7_stationary/slurm.slurm
Sat 08 Feb 2014 03:42:07 AM EST      0 KiB ./058_h2_f7_stationary/1581061.err
Sat 08 Feb 2014 03:42:14 AM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.class
Sat 08 Feb 2014 03:58:28 AM EST  70016 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mph
Sat 08 Feb 2014 04:12:40 AM EST  70304 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mph
Sat 08 Feb 2014 04:12:53 AM EST  70304 KiB ./058_h2_f7_stationary/h2_f7_stationary_out_Model.mph
Sat 08 Feb 2014 04:12:53 AM EST      0 KiB ./058_h2_f7_stationary/h2_f7_stationary_out.mph.status
Sat 08 Feb 2014 04:12:53 AM EST     32 KiB ./058_h2_f7_stationary/1581061.out
Mon 10 Feb 2014 11:40:54 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mat
Mon 10 Feb 2014 11:42:32 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mat
Mon 10 Feb 2014 11:50:08 AM EST     32 KiB ./plot_grid.m

Eu deliberadamente fiz o campo do tamanho do arquivo 6 caracteres, porque se for mais longo, torna-se difícil distinguir visualmente o tamanho dos arquivos. Desta forma, arquivos maiores que 1e6 KiB sobressaem: por 1 char significa 1-9 GB, por 2 chars significa 10-99 GB, etc.


Edit: aqui está outra versão (desde find . -printf "%Tc" falha no MinGW / MSYS):

find . -type f -printf "%T@\t%p\n" | sort -n | cut -f 2- | xargs -I{} ls -Glath --si {}

Dando saída como:

-rw-r--r-- 1 es 23K Jul 10  2010 ./laptop_0000071.jpg
-rw-r--r-- 1 es 43M Jul 29 19:19 ./work.xcf
-rw-r--r-- 1 es 87K Jul 29 20:11 ./patent_lamps/US Patent 274427 Maxim Lamp Holder.jpg
-rw-r--r-- 1 es 151K Jul 29 20:12 ./patent_lamps/Edison screw-in socket.png
-rw-r--r-- 1 es 50K Jul 29 20:13 ./patent_lamps/1157 Lamp.jpg
-rw-r--r-- 1 es 38K Jul 29 20:14 ./patent_lamps/US06919684-20050719-D00001.png

Onde:

  • -I{} provoca a ocorrência de {} para ser substituído por um argumento, e newlines são agora os separadores de argumentos (observe os espaços nos nomes de arquivos acima).

  • ls -G suprime a impressão do nome do grupo (desperdício de espaço).

  • ls -h --si produz arquivos de arquivos legíveis para humanos (mais correto com --si).

  • ls -t classifica por tempo, o que é irrelevante aqui, mas é o que eu geralmente uso.


3



Nota: para classificar por arquivo Tamanho em vez disso, basta substituir o T@ de s em qualquer um dos comandos acima. - Evgeni Sergeev


OS X variante da resposta @ user195696:

  1. Com timestamp:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r
    
  2. Sem timestamp:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r | awk -F' ' '{ print substr($0, length($1) + 2) }'
    

2





Descobri que isso é feito no Mac OS X (e genérico o suficiente para funcionar em outros Unixen também):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort

1



Infelizmente, isso imprime nomes de meses localizados na minha configuração croata, tornando a classificação incorreta. - Ivan Vučica
Resposta de user195696 trabalha para a configuração croata (e outros). - Peter Mortensen


Se seu find seleção é muito simples, você pode ser capaz de fazer sem ela, e apenas usar ls:

ls -1 *.cc # -r -t optional

1





Usar:

find . -type f -mtime 0 -printf "[%TD %TI:%TM%Tp] %s %p\n" | sort -n | awk '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

Esse comando classificará os arquivos por data de modificação.

E exibir como:

[12/05/13 03:10PM] 1.75 MB ./file.text
[12/06/13 11:52PM] 2.90 MB ./file2.mp4
[12/07/13 04:11PM] 4.88 MB ./file3.mp4
[12/07/13 09:17PM] 4.74 MB ./test.apk

1



Eu melhorei este sript para lidar com espaços em branco em nomes de arquivos, veja superuser.com/a/777007/134532 - jan


Eu não acho find tem alguma opção para modificar a ordem de saída. -mtime e -mmin permitirá restringir os resultados a arquivos que foram modificados dentro de uma determinada janela de tempo, mas a saída não será ordenada - você terá que fazer isso sozinho. GNU find tem um -printf opção que, entre outras coisas, permitirá imprimir o tempo de modificação de cada arquivo encontrado (formato strings %t ou %Tk); que pode ajudá-lo a classificar o find saída do jeito que você deseja.


0





Eu melhorei a resposta do Akashs, fazendo o script manipular os espaços em branco nos nomes dos arquivos corretamente:

find . -type f -mtime 0 -printf ";[%TD %TI:%TM%Tp];%s;%p\n" | sort -n | awk -F ";" '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

0