Come posso elencare ricorsivamente tutti i file che sono stati modificati tra il 22.12.2011 e il 24.12.2011?
Come posso elencare ricorsivamente tutti i file che sono stati modificati tra il 22.12.2011 e il 24.12.2011?
Risposte:
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 -newer
predicato.
touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop
-newer
è necessario qui?
-newer
non è negato, il secondo è. "Trova file più recenti di start
ma non più recenti di stop
".
start
e stop
.
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.
find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l
( -m 50
= ricerca nelle prime 50 righe).
-exec ... +
in find(1)
, come: find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +
. Questo fa lo stesso, ma è più economico.
find 4.7.0-git
).
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 cmin
a mmin
dopo il commento di @ Eelvex.
EDIT: '\!' mancante
-cmin
è "modifica dello stato", -mmin
è "modifica dei dati". Probabilmente vuoi-mmin
find
può 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
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!