Come elencare i file che sono stati modificati in un determinato intervallo di tempo?


38

Come posso elencare ricorsivamente tutti i file che sono stati modificati tra il 22.12.2011 e il 24.12.2011?


6
Se intendi "ultimo cambiamento", hai la possibilità di trovare una soluzione. Se un file è stato modificato il 26.12.2011, non è possibile sapere se è stato modificato anche durante l'intervallo specificato. (A meno che tu non abbia un file system molto esotico.)
William Pursell il

Risposte:


25

In generale, quando cerchi ricorsivamente file in una directory e nelle sue sottodirectory, usa find.

Il modo più semplice per specificare un intervallo di date findè quello di creare file ai limiti dell'intervallo e utilizzare il -newerpredicato.

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop

perché negare l'output del primo -newerè necessario qui?
Alexander Cska,

@AlexanderCska Il primo -newernon è negato, il secondo è. "Trova file più recenti di startma non più recenti di stop".
Gilles 'SO- smetti di essere malvagio' il

Ok la negazione funziona dopo il comando. Cosa accadrebbe se non fosse presente alcuna negazione?
Alexander Cska,

@AlexanderCska Quindi otterrai i file più recenti di entrambi starte stop.
Gilles 'SO- smetti di essere malvagio' il

35

Usando la soluzione di Gilles e dopo aver letto di nuovo l' uomo trova (1) ho trovato una soluzione più semplice. L'opzione migliore è -newerXY. È possibile utilizzare i flag m et.

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

Quindi la soluzione è

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

Il limite inferiore in inclusivo e il limite superiore sono esclusivi, quindi ho aggiunto 1 giorno ad esso! Ed è ricorsivo. Funziona bene su find v4.5.9.


Bel trucco, grazie! Ciò mi ha aiutato a trovare un file recente contenente una determinata parola chiave in una directory con migliaia di file: find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l( -m 50= ricerca nelle prime 50 righe).
Rob W,

@RobW: In realtà si può risparmiare il tubo e xargs utilizzare -exec ... +in find(1), come: find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +. Questo fa lo stesso, ma è più economico.
TrueY

Ho dovuto racchiudere i timestamp con una doppia citazione (sono su Ubuntu Xenial con find 4.7.0-git).
Isacco

13

Oltre alle risposte già fornite, tieni presente che puoi specificare direttamente le tue date:

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

o

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

se si desidera inoltre specificare l'ora.


6

Supponendo che non occorra precisione ai secondi, questo dovrebbe funzionare.

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

EDIT: modificato cmina mmindopo il commento di @ Eelvex. EDIT: '\!' mancante


hm non sembra funzionare. sei sicuro che attraversi ricorsivamente le sottodirectory?
morsetto

Sì, funziona su di me. Hai davvero dei file modificati in quell'intervallo di tempo? Provalo con diversi intervalli di tempo.
onur güngör,

6
-cminè "modifica dello stato", -mminè "modifica dei dati". Probabilmente vuoi-mmin
Eelvex il

3

findpuò richiedere un datetime in formato ISO, quindi per un server su UTC, ad esempio, è possibile specificare un offset di un numero di ore da qualsiasi luogo. Questo si occupa anche di dover aggiungere un giorno poiché stai confrontando anche il tempo:

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800

0

Si prega di notare che la domanda contrassegnata come duplicata, e quindi è limitata dal rispondere direttamente, è il motivo per cui sto postando qui. Questa risposta è per rispondere alla domanda "necessità di spostare i file in cartelle diverse in base alla data di creazione [duplicato]"

Le risposte sono ragionevoli ma c'erano alcune limitazioni con un comando puramente find. Ho scritto questo script di shell per passare attraverso una directory con così tanti file al suo interno che il filesystem stava imbavagliando i metadati nel tentativo di eseguire una ls. Inoltre alcuni sistemi * nix segnalano un errore di troppi argomenti durante l'esecuzione di ls.

Il comando find è molto potente e ho iniziato con i metodi elencati ma ho avuto così tanti anni di dati in quella directory che ho dovuto passare più volte su tutti i file. Questo produce molti passaggi inutili su ogni file. Ho provato a fare una schermata all'anno ed eseguire più rilevamenti, ma ciò ha comportato molti errori da ogni individuazione e i file sarebbero scomparsi quando uno dei rilevamenti lo ha spostato.

Il mio script shell sposta un file nella directory di destinazione, con un anno a 4 cifre e un mese a 2 cifre. Può essere facilmente esteso a un giorno a 2 cifre decommentando un paio di righe e commentando le loro controparti. Credo che sia più efficiente perché è stato eseguito i movimenti in un passaggio di ricerca, quindi non sono necessari più comandi di ricerca e passaggi sulla directory.

#!/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

Una volta salvato e reso eseguibile, puoi chiamare questo script con find come il seguente.

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

Non devi preoccuparti di impostare l'opzione newermt per find poiché tutto ciò che find sta fornendo è una singola esecuzione per file trovato e lo script prende tutte le decisioni.

Tenere presente che se non si seleziona -type f, le directory verranno spostate e ciò potrebbe causare problemi. Puoi anche usare -type d se stai cercando di spostare solo le directory. Non impostare il tipo produrrà quasi certamente comportamenti indesiderati.

Ricorda che questa sceneggiatura è stata adattata alle mie esigenze. Potresti semplicemente usare il mio costrutto come ispirazione per uno script più adatto alle tue esigenze. Grazie!

Considerazioni: L'efficienza del comando può essere MASSIMAMENTE migliorate consentendo un numero illimitato di argomenti da passare attraverso lo script. Questo è in realtà relativamente semplice se si passa sopra la variabile $ @. L'estensione della funzionalità di questo ci consentirebbe di utilizzare la funzione -exec + di find o di sfruttare xargs, per esempio. Potrei implementarlo rapidamente e migliorare la mia risposta, ma questo è un inizio.

Poiché questa è stata una sessione di script one-shot, probabilmente ci sono molti miglioramenti che possono essere fatti. In bocca al lupo!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.