Come spostare i file in base all'anno


14

Devo spostare i file in base a un anno. Ho usato il findcomando

find /media/WD/backup/osool/olddata/ -mtime +470 -exec ls -lrth {} \;|sort -k6

ma per eseguire correttamente questo comando devo sapere che mtimeora 470 è solo una supposizione. Significa che se posso dare l'anno 2012, mi dà solo i file relativi al 2012.

Quindi ho bisogno di consigli su come

Trova i file in base all'anno, ad esempio 2012 e spostali in un'altra directory.

OS release 5.2

FIND version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX 

Ha senso usare -exec ls ... \;invece di -exec ... +? La tua scoperta è troppo vecchia per quello? In tal caso find ... -print0 | xargs -0 ls...sarebbe molto più veloce.
Hauke ​​Laging,

Vorrei che queste domande (e risposte) che trattano di coreutils specifichino sistematicamente se abbiamo a che fare con GNU o BSD (o altri) programmi di utilità.
labirinto,

Risposte:


37

Vuoi usare l' -newermtopzione per find:

find /media/WD/backup/osool/olddata/ -newermt 20120101 -not -newermt 20130101

per ottenere tutti i file con tempo di modifica nel 2012.

Se la tua ricerca non supporta -newermt, puoi anche fare quanto segue per impedire l'uso dei calcoli di offset:

touch -d 20120101 /var/tmp/2012.ref
touch -d 20130101 /var/tmp/2013.ref
find /media/WD/backup/osool/olddata/ -newer /var/tmp/2012.ref -not -newer /var/tmp/2013.ref

1
-newermt flag non è disponibile nel comando Trova
OmiPenguin il

Deve essere una vecchia versione di find con cui viene fornito il tuo RHEL?
Anthon,

Sì, questo è il 5.2
OmiPenguin il

Presumo che sia la revisione di RHEL, non di find(ho trovato la versione 4.4.2)
Anthon,

1
Il nuovo switch non è stato mostrato in find fino alle versioni successive alla v4.3.3, gnu.org/software/findutils/manual/html_mono/find.html .
slm

5
touch --date=2011-12-31T23:59:59 start
touch --date=2012-12-31T23:59:59 stop
find / -newer start \! -newer stop -printf %Tx" "%p\\n

-exec ls non ha alcun senso.


1
-exec ls -lha più senso e anche di più durante i test.
un CVn il

@ MichaelKjörling findpuò stampare tutto ciò che lspuò. OK, con una sola eccezione: fuga / quotazione di caratteri spiacevoli. Ma in generale l'output di findpuò essere ordinato direttamente. Chiamate inutili di ls non rendono il tutto più veloce.
Hauke ​​Laging,

Molto spesso uso qualcosa di abbastanza simile (anche se personalmente preferisco -printo forse -ls ) durante i test. Il vantaggio dell'uso -exec ls {}è che esegue già qualcosa di esterno da trovare . Quindi, al momento del passaggio da lsa mv, le modifiche effettive sono minime.
un CVn il

3

Secondo la pagina man, l'argomento -mtime è il numero di giorni che stai cercando. È possibile utilizzare date +%jper trovare il numero di giorni dal 1 ° gennaio dell'anno corrente.


2
Bel modo. Per essere molto "nitpicky": -mtime -1: è qualsiasi file nelle ultime 24 ore. Non solo i file di ieri (o di oggi). Quindi, ci sarà anche un po 'di "sovrapposizione": se determini che sono passati 120 giorni dal 2012, e oggi sono le 15:45 quando avvii lo script, finirai per selezionare i file fino al 31 dic 15:45 ( e non gli ultimi di quel giorno) ... Probabilmente puoi usare: nb_day - 1, e poi "estirpare" i pochi che risalgono al 2013 (quelli potrebbero essere trovati da un ls -l | grep -v, MA l'output differisce se hanno solo 1 giorno ... molte insidie ​​...)
Olivier Dulac

Vuoi usare l' -daystartopzione se hai intenzione di lavorare -mtime. Altrimenti avrai problemi con i file all'inizio e alla fine dell'anno, qualunque sia il modo in cui ti giri a meno che tu non lo esegua esattamente a mezzanotte. Puoi eseguire l'offset in modo più accurato -mminrispetto a con -mtimese riesci a trovare facilmente il numero di minuti dal nuovo anno. Ma lo stesso problema esiste con quello di -mtime, solo per un minor numero di file (quelli un minuto intorno a mezzanotte di nuovo anno).
Anthon,

1
Sì, rileggendo la pagina man sto vedendo come si scompone in ore, quindi fare un semplice find -mtime $("date -+%j")probabilmente non darà all'OP quello che stanno cercando. Lo sto lasciando per i posteri, dato che questo sembra un possibile punto cieco in cui le persone possano cadere.
Bratchley,

2

Puoi provare a usare una combinazione con i comandi state / o datecome nei seguenti one-liner:

BSD / Mac OS X:

find . -type f -print | while read file; do eval `stat -s "$file"`; year=`date -jf "%s" "+%Y" "$st_mtime"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

Linux:

find . -type f -print | while read file; do year=`date -r "$file" "+%Y"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

In entrambi i casi, l'approccio consiste nell'utilizzare il datecomando per estrarre l'anno dall'ultima modifica di ogni file e quindi per costruire un percorso con quest'anno. Il comando mkdir -pcreerà questo percorso se non esiste già. Ovviamente puoi usare alcune altre findopzioni per affinare la tua ricerca.


1

Se lo fai dalla directory di lavoro, puoi invece farlo:

ls -l |awk '{ if ($8 == "2013") print $9 }'

Questo semplifica notevolmente le cose e non causa sovrapposizioni. Ma presuppone anche che questi file siano più vecchi di 6 mesi e che lsstamperanno l'anno anziché l'ora esatta.

Per i file più recenti di 6 mesi, dovrai solo sostituirlo con questo:

ls -l |awk '{ if ($6 == "May") print $9 }' 

o qualcosa di simile, a seconda del mese. Se si desidera creare un elenco di mesi per cui spostare i file (o se si desidera creare un elenco per anni), procedere come segue:

month="May Jun Jul"; 
for i in `echo $month`; 
do 
    for j in `ls -l |awk '{ if ($6 == "'$i'") print $9}'`
    do
        mkdir -p $i
        mv $j $i
    done
done
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.