Parece que ls
não classifica os arquivos corretamente ao fazer uma chamada recursiva:
ls -altR . | head -n 3
Como posso encontrar o arquivo modificado mais recentemente em um diretório (incluindo subdiretórios)?
Parece que ls
não classifica os arquivos corretamente ao fazer uma chamada recursiva:
ls -altR . | head -n 3
Como posso encontrar o arquivo modificado mais recentemente em um diretório (incluindo subdiretórios)?
Respostas:
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "
Para uma árvore enorme, pode ser difícil sort
manter tudo na memória.
%T@
fornece o tempo de modificação, como um carimbo de data / hora unix, sort -n
classifica numericamente, tail -1
pega a última linha (carimbo de data / hora mais alta), cut -f2 -d" "
corta o primeiro campo (o carimbo de data / hora) da saída.
Edit: Assim como -printf
provavelmente é apenas o GNU, stat -c
também é possível o uso de um novo. Embora seja possível fazer o mesmo no BSD, as opções de formatação são diferentes ( -f "%m %N"
ao que parece)
E eu perdi a parte do plural; se você quiser mais do que o arquivo mais recente, basta aumentar o argumento da cauda.
sort -rn | head -3
em vez de sort -n | tail -3
. Uma versão fornece os arquivos do mais antigo para o mais novo, enquanto a outra passa do mais recente para o mais antigo.
sort
criará arquivos temporários (in /tmp
) conforme necessário, então não acho que seja uma preocupação.
-printf '%T@ %Tb %Td %TY %p\n'
vai dar-lhe um carimbo de data (se necessário) (semelhante a ls
)
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Seguindo a resposta da @ plundra , aqui está a versão BSD e OS X:
find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
find
suporta, em +
vez de \;
? Porque isso faz a mesma coisa (passando vários arquivos como parâmetros), sem o -print0 | xargs -0
pipe.
head -1
parahead -5
Em vez de classificar os resultados e manter apenas os últimos modificados, você pode usar o awk para imprimir apenas aquele com maior tempo de modificação (em tempo unix):
find . -type f -printf "%T@\0%p\0" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\0'
Essa deve ser uma maneira mais rápida de resolver seu problema se o número de arquivos for grande o suficiente.
Eu usei o caractere NUL (ou seja, \ 0 ') porque, teoricamente, um nome de arquivo pode conter qualquer caractere (incluindo espaço e nova linha), exceto isso.
Se você não possui esses nomes de arquivos patológicos em seu sistema, também pode usar o caractere de nova linha:
find . -type f -printf "%T@\n%p\n" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\n'
Além disso, isso também funciona em mawk.
mawk
a alternativa padrão do Debian.
Ocorreu um problema ao encontrar o último arquivo modificado no Solaris 10. Não find
existe a printf
opção e stat
não está disponível. Eu descobri a seguinte solução que funciona bem para mim:
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1
Para mostrar o nome do arquivo, use
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1
Explicação
find . -type f
localiza e lista todos os arquivossed 's/.*/"&"/'
agrupa o nome do caminho entre aspas para lidar com espaços em brancoxargs ls -E
envia o caminho entre aspas para ls
, a -E
opção garante que um registro de data e hora completo (formato ano-mês-dia hora-minuto-segundos-nanossegundos ) seja retornadoawk '{ print $6," ",$7 }'
extrai apenas data e horaawk '{ print $6," ",$7," ",$9 }'
extrai data, hora e nome do arquivosort
retorna os arquivos classificados por datatail -1
retorna apenas o último arquivo modificadoIsso parece funcionar bem, mesmo com subdiretórios:
find . -type f | xargs ls -ltr | tail -n 1
No caso de muitos arquivos, refine a localização.
-l
opção de ls
parece desnecessária. Apenas -tr
parece suficiente.
find . -type f -print0 | xargs -0 ls -ltr | tail -n 1
Mostra o arquivo mais recente com carimbo de data / hora legível por humanos:
find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1
O resultado fica assim:
2015-10-06 11:30: +0200 ./foo/bar.txt
Para mostrar mais arquivos, substitua -n1
por um número maior
Eu uso algo semelhante o tempo todo, bem como a lista top-k dos arquivos modificados mais recentemente. Para árvores de diretório grandes, pode ser muito mais rápido evitar a classificação . No caso dos top-1 arquivo modificado mais recentemente:
find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'
Em um diretório que contém 1,7 milhão de arquivos, recebo o mais recente do 3.4s, uma aceleração de 7.5x em relação à solução 25.5s usando sort.
lastfile
) e, em seguida, você pode fazer o que quiser com o resultado, tais como ls -l $(lastfile .)
, ou open $(lastfile .)
(em um Mac), etc.
No Ubuntu 13, o seguinte é feito, talvez um pouco mais rápido, pois inverte o tipo e usa 'head' em vez de 'tail', reduzindo o trabalho. Para mostrar os 11 arquivos mais recentes em uma árvore:
encontrar . -tipo f -printf '% T @% p \ n' | ordenar -n -r | cabeça -11 | corte -f2- -d "" | sed -e 's, ^. / ,,' | xargs ls -U -l
Isso fornece uma lista completa de ls sem reclassificar e omite o irritante './' que 'find' coloca em cada nome de arquivo.
Ou, como uma função bash:
treecent () {
local numl
if [[ 0 -eq $# ]] ; then
numl=11 # Or whatever default you want.
else
numl=$1
fi
find . -type f -printf '%T@ %p\n' | sort -n -r | head -${numl} | cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}
Ainda assim, a maior parte do trabalho foi realizada pela solução original da plundra. Graças plundra.
Eu enfrentei o mesmo problema. Preciso encontrar o arquivo mais recente recursivamente. find levou cerca de 50 minutos para encontrar.
Aqui está um pequeno script para fazê-lo mais rápido:
#!/bin/sh
CURRENT_DIR='.'
zob () {
FILE=$(ls -Art1 ${CURRENT_DIR} | tail -n 1)
if [ ! -f ${FILE} ]; then
CURRENT_DIR="${CURRENT_DIR}/${FILE}"
zob
fi
echo $FILE
exit
}
zob
É uma função recursiva que obtém o item modificado mais recente de um diretório. Se este item for um diretório, a função é chamada recursivamente e pesquisa nesse diretório, etc.
Acho o seguinte mais curto e com saída mais interpretável:
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Dado o comprimento fixo das datas padronizadas no formato ISO, a classificação lexicográfica é boa e não precisamos da -n
opção na classificação.
Se você deseja remover os carimbos de data e hora novamente, pode usar:
find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '
Se a execução stat
de cada arquivo individualmente for lenta, use-a xargs
para acelerar um pouco as coisas:
find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" "
Isso altera recursivamente o tempo de modificação de todos os diretórios no diretório atual para o arquivo mais recente em cada diretório:
for dir in */; do find $dir -type f -printf '%T@ "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done
Este CLI simples também funcionará:
ls -1t | head -1
Você pode alterar o -1 para o número de arquivos que deseja listar
Achei o comando acima útil, mas, para o meu caso, eu precisava ver a data e a hora do arquivo e também tive um problema com vários arquivos com espaços nos nomes. Aqui está a minha solução de trabalho.
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10
Manipula bem os espaços nos nomes de arquivos - não que eles devam ser usados!
2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht
Mais find
abundância seguindo o link.
Para procurar arquivos no diretório / target_directory e todos os seus subdiretórios, que foram modificados nos últimos 60 minutos:
$ find /target_directory -type f -mmin -60
Para encontrar os arquivos modificados mais recentemente, classificados na ordem inversa do tempo de atualização (ou seja, os arquivos atualizados mais recentemente):
$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r
Eu prefiro este, é mais curto:
find . -type f -print0|xargs -0 ls -drt|tail -n 1
Eu escrevi um pacote pypi / github para esta pergunta porque também precisava de uma solução.
https://github.com/bucknerns/logtail
Instalar:
pip install logtail
Uso: caudas arquivos alterados
logtail <log dir> [<glob match: default=*.log>]
Uso2: Abre o último arquivo alterado no editor
editlatest <log dir> [<glob match: default=*.log>]