Jak przenieść pliki na podstawie roku

15

Muszę przenosić pliki na podstawie roku. Użyłem findpolecenia

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

ale aby to polecenie mogło zostać pomyślnie wykonane, muszę dokładnie wiedzieć, że mtime470 to tylko przypuszczenie. Znaczy, czy mogę podać rok 2012, daje mi pliki związane tylko z rokiem 2012.

Potrzebuję porady, jak to zrobić

Znajdź pliki na podstawie roku, np. 2012 i przenieś je do innego katalogu.

OS release 5.2

FIND version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX 
OmiPenguin
źródło
Czy warto używać -exec ls ... \;zamiast tego -exec ... +? Czy twoje znalezisko jest na to za stare? W takim przypadku find ... -print0 | xargs -0 ls...byłoby znacznie szybciej.
Hauke ​​Laging
Chciałbym, aby te pytania (i odpowiedzi) dotyczące coreutils rutynowo określały, czy mamy do czynienia z narzędziami GNU, BSD (lub innymi).
labirynt

Odpowiedzi:

39

Chcesz użyć -newermtopcji dla find:

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

aby uzyskać wszystkie pliki z czasem modyfikacji w 2012 roku.

Jeśli wyszukiwanie nie obsługuje -newermt, możesz również wykonać następujące czynności, aby zapobiec korzystaniu z obliczeń przesunięcia:

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
Anthon
źródło
1
-nowa flaga nie jest dostępna w poleceniu Znajdź
OmiPenguin
To musi być stara wersja znaleziska, w którą wyposażony jest Twój RHEL? W odpowiedzi podam alternatywę
Anthon
Tak, ten jest 5.2
OmiPenguin
Rozumiem, że jest to wersja RHEL, a nie find(znalazłem wersję 4.4.2)
Anthon
1
Przełącznik newermt nie pojawił się w find aż do wersji po 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 nie ma żadnego sensu.

Hauke ​​Laging
źródło
1
-exec ls -lma więcej sensu, a nawet więcej podczas testowania.
CVn
@ MichaelKjörling findmoże wydrukować wszystko, co lsmoże. OK, z jednym wyjątkiem: ucieczka / cytowanie nieprzyjemnych znaków. Ale ogólnie wyniki findmożna sortować bezpośrednio. Bezużyteczne wezwania ls nie przyspieszają.
Hauke ​​Laging
Bardzo często używam czegoś całkiem podobnego (chociaż osobiście wolę -printlub ewentualnie -ls ) podczas testowania. Zaletą użycia -exec ls {}jest to, że już wykonuje coś zewnętrznego do znalezienia . Więc w momencie przełączenia z lsna mvrzeczywiste zmiany są minimalne.
CVn
3

Według strony podręcznika argumentem -mtime jest liczba dni, których szukasz. Możesz użyć, date +%jaby znaleźć liczbę dni od 1 stycznia bieżącego roku.

Bratchley
źródło
2
Dobry sposób. Aby być bardzo „drobiazgowym”: -mtime -1: to dowolny plik z ostatnich 24 godzin. Nie tylko pliki z wczoraj (lub dzisiaj). Tak więc będzie też trochę „nakładania się”: jeśli stwierdzisz, że minęło 120 dni od 2012 roku, a dziś jest 15:45 po uruchomieniu skryptu, ostatecznie wybierzesz pliki do 31 grudnia 15:45 ( a nie ostatnie tego dnia) ... Prawdopodobnie możesz użyć: nb_day - 1, a następnie „wyeliminować” tych, którzy pochodzą z 2013 roku (można je znaleźć przy pomocy ls -l | grep -v, ALE wyniki różnią się, jeśli mają tylko 1 dzień ... wiele pułapek ...)
Olivier Dulac
Jeśli chcesz pracować, chcesz skorzystać z tej -daystartopcji -mtime. W przeciwnym razie będziesz mieć problemy z plikami na początku i na końcu roku, niezależnie od tego, w którą stronę się skręcisz, chyba że uruchomisz to dokładnie o północy. Możesz dokonać przesunięcia dokładniej -mminniż za pomocą, -mtimejeśli możesz łatwo znaleźć liczbę minut od nowego roku. Ale ten sam problem istnieje z tym, co z -mtime, tylko dla mniejszej liczby plików (tych o minutę około północy nowego roku).
Anthon
1
Tak, ponownie czytam stronę podręcznika. Widzę, jak to rozkłada się na godziny, więc wykonanie prostej find -mtime $("date -+%j")prawdopodobnie nie da OP tego, co zamierzają. Pozostawiam to potomności, ponieważ wydaje się, że może to być ślepa plamka dla ludzi, w którą można wpaść.
Bratchley,
2

Możesz spróbować użyć kombinacji z komendami stati / lub datejak w następujących linijkach:

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

W obu przypadkach podejście polega na użyciu datepolecenia do wyodrębnienia roku z czasu ostatniej modyfikacji każdego pliku, a następnie do utworzenia ścieżki z tym rokiem. Polecenie mkdir -putworzy tę ścieżkę, jeśli jeszcze nie istnieje. Oczywiście możesz użyć innych findopcji, aby zawęzić wyszukiwanie.

woodengod
źródło
1

Jeśli zrobisz to z katalogu roboczego, możesz to zrobić w zamian:

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

Upraszcza to znacznie i nie powoduje nakładania się. Ale zakłada również, że te pliki są starsze niż 6 miesięcy i że lswydrukuje rok zamiast dokładnej godziny.

W przypadku plików starszych niż 6 miesięcy musisz po prostu zastąpić to:

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

lub coś podobnego, w zależności od miesiąca. Jeśli chcesz utworzyć listę miesięcy, dla których chcesz przenieść pliki (lub jeśli chcesz utworzyć listę na lata):

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
Ernie
źródło