Como listar arquivos que foram alterados em um determinado intervalo de tempo?

38

Como posso listar recursivamente todos os arquivos que foram alterados entre 22.12.2011 e 24.12.2011?

braçadeira
fonte
6
Se você quer dizer "última alteração", tem uma chance de encontrar uma solução. Se um arquivo foi modificado em 26.12.2011, você não pode dizer se ele também foi modificado durante o intervalo especificado. (A menos que você tem um sistema de arquivos muito exótico.)
William Pursell

Respostas:

25

De um modo geral, quando você estiver procurando arquivos em um diretório e seus subdiretórios recursivamente, use find.

A maneira mais fácil de especificar um intervalo de datas findé criar arquivos nos limites do intervalo e usar o -newerpredicado.

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop
Gilles 'SO- parar de ser mau'
fonte
por que negar a saída do primeiro -neweré necessário aqui?
21818 Alexander Cska
@AlexanderCska O primeiro -newernão é negado, o segundo é. "Encontre arquivos que são mais recentes que, startmas não novos, que stop".
Gilles 'SO- stop be evil'
Ok, a negação funciona no comando depois. O que aconteceria se nenhuma negação estivesse presente?
Alexander Cska
@AlexanderCska Então você obteria os arquivos mais novos que ambos starte stop.
Gilles 'SO- stop be evil'
35

Usando a solução de Gilles e depois de ler o homem, encontre (1) novamente, encontrei uma solução mais simples. A melhor opção é o -newerXY. Os sinalizadores m e t podem ser usados.

m   The modification time of the file reference
t   reference is interpreted directly as a time

Então a solução é

find . -type f -newermt 20111222 \! -newermt 20111225

O limite inferior em inclusivo e o limite superior são exclusivos, então eu adicionei 1 dia a ele! E é recursivo. Funciona bem no find v4.5.9.

TrueY
fonte
Truque legal, obrigado! Isso me ajudou a encontrar um arquivo recente contendo uma determinada palavra-chave em um diretório com milhares de arquivos: find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l( -m 50= pesquisa nas primeiras 50 linhas).
Rob W
@RobW: Na verdade você pode poupar o tubo e xargs usando -exec ... +em find(1), como: find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +. Isso faz o mesmo, mas mais barato.
TrueY 13/02/2015
Eu tive que colocar os timestamps com aspas duplas (estou no Ubuntu Xenial com find 4.7.0-git).
Isaacs
13

Além das respostas já dadas, observe que você pode especificar diretamente suas datas:

find -type f -newermt "2011-12-22" \! -newermt "2011-12-24"

ou

find -type f -newermt "2011-12-22 00:00:00" \! -newermt "2011-12-24 13:23:00"

se você desejar especificar adicionalmente a hora.

aluna
fonte
6

Supondo que você não precise de precisão em segundos, isso deve funcionar.

find . -type f -mmin -$(((`date +%s`-`date -d 20111222 +"%s"`)/60)) \! -mmin +$(((`date +%s`-`date -d 20111224 +"%s"`)/60))

EDIT: Alterado cminpara mminapós o comentário de @ Eelvex. EDIT: '\!' ausência de

onur güngör
fonte
hm parece não funcionar. você tem certeza de que percorre recursivamente os subdiretórios?
clamp
Sim, funciona em mim. Você realmente tem arquivos modificados nesse período? Experimente com diferentes intervalos de tempo.
Onur
6
-cminé "alteração de status", -mminé "alteração de dados". Você provavelmente quer-mmin
Eelvex
3

findpode levar um datetime no formato ISO; portanto, para um servidor no UTC, por exemplo, você pode especificar um deslocamento de várias horas a partir de onde estiver. Isso também garante a adição de um dia, pois você também está comparando o tempo:

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800
Alex Young
fonte
0

Observe que a pergunta marcada como duplicada e, portanto, não pode responder diretamente, é por isso que estou postando aqui. Esta resposta é para responder à pergunta "precisa mover arquivos para uma pasta diferente com base na data de criação [duplicada]"

As respostas são razoáveis, mas houve algumas limitações com um comando puramente encontrar. Eu escrevi esse shell script para percorrer um diretório com tantos arquivos, que o sistema de arquivos estava engasgando com os metadados tentando executar um ls. Além disso, alguns sistemas * nix apresentam um erro de muitos argumentos ao executar ls.

O comando find é muito poderoso e comecei com os métodos listados, mas eu tinha tantos anos de dados nesse diretório que precisei passar todos os arquivos repetidamente. Isso produz um monte de desnecessário passado por cada arquivo. Tentei fazer uma tela por ano e executar várias descobertas, mas isso resultou em muitos erros em cada descoberta e os arquivos desapareceriam quando uma das descobertas a movia.

Meu script de shell move um arquivo para o diretório de destino, com um ano de 4 dígitos e um mês de 2 dígitos. Ele pode ser facilmente expandido para um dia de 2 dígitos, descomentando algumas linhas e comentando suas contrapartes. Eu acredito que é mais eficiente porque foi executar os movimentos em uma passagem de localização, de modo que vários comandos e passagens sobre o diretório são desnecessários.

#!/bin/bash
#We want to exit if there is no argument submitted
if [ -z "$1" ]
then
  echo no input file
  exit
fi

#destDir should be set to where ever you want the files to go
destDir="/home/user/destination"

#Get the month and year of modification time
#--format %y returns the modification date in the format:
# 2016-04-26 12:40:48.000000000 -0400
#We then take the first column, split by a white space with awk
date=`stat "$1" --format %y | awk '{ print $1 }'`

#This sets the year variable to the first column split on a - with awk
year=`echo $date | awk -F\- '{print $1 }'`
#This sets the month variable to the second column split on a - with awk
month=`echo $date | awk -F\- '{print $2 }'`
#This sets the day variable to the third column split on a - with awk
#This is commented out because I didn't want to add day to mine
#day=`echo $date | awk -F\- '{print $3 }'`

#Here we check if the destination directory with year and month exist
#If not then we want to create it with -p so the parent is created if
# it doesn't already exist
if [ ! -d $destDir/$year/$month ]
then
  mkdir -p $destDir/$year/$month || exit
fi

#This is the same as above but utilizes the day subdirectory
#Uncommented this out and comment out the similar code above
#if [ ! -d $destDir/$year/$month/$day ]
#then
#  mkdir -p $destDir/$year/$month$day || exit
#fi

#Echoing out what we're doing
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
echo Moving $1 to $destDir/$year/$month
#echo Moving $1 to $destDir/$year/$month/$day

#Move the file to the newly created directory
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
mv "$1" $destDir/$year/$month
#mv "$1" $destDir/$year/$month/$day

Uma vez salvo e tornado executável, você pode chamar esse script com os seguintes itens.

find /path/to/directory -type f -exec /home/username/move_files.sh {} \;

Você não precisa se preocupar em definir a opção newermt para find, pois tudo o que find está fornecendo é uma única execução por arquivo encontrado e o script toma todas as decisões.

Lembre-se de que, se você não selecionar -type f, os diretórios serão movidos e provavelmente causarão problemas. Você também pode usar -type d se estiver procurando mover apenas diretórios. Não definir o tipo quase certamente produzirá comportamento indesejado.

Lembre-se de que esse script foi adaptado às minhas necessidades. Você pode simplesmente usar minha construção como inspiração para um script mais adequado às suas necessidades. Obrigado!

Considerações: A eficiência do comando pode ser EXTREMAMENTE melhorada, permitindo que um número ilimitado de argumentos passe pelo script. Isso é relativamente fácil se você passar a variável $ @. Estender a funcionalidade disso nos permitiria usar a função -exec + do find ou alavancar xargs, por exemplo. Posso implementar isso rapidamente e melhorar minha própria resposta, mas isso é um começo.

Como essa foi uma sessão de script única, provavelmente há muitas melhorias que podem ser feitas. Boa sorte!

Vex Mage
fonte