Jak wyświetlić listę plików, które zostały zmienione w określonym przedziale czasu?


38

Jak mogę rekurencyjnie wyświetlić listę wszystkich plików, które zostały zmienione między 22.12.2011 a 24.12.2011?


6
Jeśli masz na myśli „ostatnia zmiana”, masz szansę na rozwiązanie. Jeśli plik został zmodyfikowany w dniu 26.12.2011, nie możesz stwierdzić, czy został on również zmodyfikowany w danym zakresie. (Chyba że masz bardzo egzotyczny system plików.)
William Pursell

Odpowiedzi:


25

Ogólnie rzecz biorąc, jeśli szukasz plików w katalogu i jego podkatalogach rekurencyjnie, użyj find.

Najłatwiejszym sposobem określenia zakresu dat findjest utworzenie plików na granicach zakresu i użycie -newerpredykatu.

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

po co tutaj negować wyjście pierwszego -newer?
Alexander Cska,

@AlexanderCska Pierwszy -newernie jest zanegowany, drugi jest. „Znajdź pliki, które są nowsze niż, startale nie nowsze niż stop”.
Gilles „SO- przestań być zły”

Ok negacja działa na polecenie po. Co by się stało, gdyby nie było żadnej negacji?
Alexander Cska,

@AlexanderCska Wtedy otrzymasz pliki, które są nowsze niż oba starti stop.
Gilles „SO- przestań być zły”

35

Korzystając z rozwiązania Gillesa i po przeczytaniu mężczyzny znajdź (1) , znalazłem prostsze rozwiązanie. Najlepszą opcją jest -newerXY. Można użyć flag m i t.

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

Więc rozwiązaniem jest

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

Dolna granica włącznie, a górna granica jest wyłączna, więc dodałem do niej 1 dzień! I to jest rekurencyjne. Działa dobrze na find v4.5.9.


Fajna sztuczka, dzięki! Pomogło mi to znaleźć najnowszy plik zawierający określone słowo kluczowe w katalogu z tysiącami plików: find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l( -m 50= szukaj w pierwszych 50 wierszach).
Rob W

@RobW: Właściwie można oszczędzić rurę i xargs korzystając -exec ... +w find(1)jak: find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +. Robi to samo, ale taniej.
TrueY

Musiałem dołączyć znaczniki czasu podwójnym cytatem (korzystam z Ubuntu Xenial find 4.7.0-git).
Izaak

13

Oprócz podanych już odpowiedzi pamiętaj, że możesz bezpośrednio określić swoje daty:

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

lub

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

jeśli dodatkowo chcesz określić czas.


6

Zakładając, że nie potrzebujesz precyzji do sekund, powinno to działać.

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

EDYCJA: Zmieniono cminna mminpo komentarzu @ Eelvex. EDYCJA: „\!” brakujący


hm nie działa. czy jesteś pewien, że rekurencyjnie przechodzi przez podkatalogi?
zacisk

Tak, działa na mnie. Czy naprawdę masz pliki zmodyfikowane w tym przedziale czasowym? Wypróbuj z różnymi zakresami czasowymi.
onur güngör

6
-cminto „zmiana stanu”, -mminto „zmiana danych”. Prawdopodobnie chcesz-mmin
Eelvex

3

findmoże zająć sformatowaną datę / godzinę w formacie ISO, więc na przykład dla serwera na UTC można określić przesunięcie liczby godzin od miejsca, w którym się znajdujesz. To również wymaga dodania dnia, ponieważ również porównujesz czas:

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

0

Pamiętaj, że pytanie oznaczone jako zduplikowane i dlatego nie ma możliwości bezpośredniej odpowiedzi na to pytanie, dlatego piszę tutaj. Ta odpowiedź służy udzieleniu odpowiedzi na pytanie „trzeba przenieść pliki do innego folderu na podstawie daty utworzenia [duplikat]”

Odpowiedzi są rozsądne, ale były pewne ograniczenia dotyczące wyłącznie polecenia znajdowania. Napisałem ten skrypt powłoki, aby przejść przez katalog z tak wieloma plikami, że system plików dławił się metadanych, próbując wykonać ls. Dodatkowo, niektóre systemy * nix nie wyświetlają zbyt wielu argumentów przy uruchamianiu ls.

Polecenie find jest bardzo wydajne i zacząłem od wymienionych metod, ale miałem tyle lat danych w tym katalogu, że musiałem wielokrotnie przesyłać wszystkie pliki. Powoduje to wiele niepotrzebnych przejść przez każdy plik. Próbowałem robić jeden ekran rocznie i uruchamiać wiele wyników, ale spowodowało to wiele błędów przy każdym znalezieniu, a pliki ginęłyby, gdy jedno z nich przeniosło je.

Mój skrypt powłoki przenosi plik do katalogu docelowego z 4-cyfrowym rokiem i 2-cyfrowym miesiącem. Można go z łatwością rozszerzyć do dwucyfrowego dnia, usuwając komentarz z kilku wierszy i komentując ich odpowiedniki. Uważam, że jest bardziej wydajny, ponieważ wykonywał ruchy w jednym przejściu find, więc wiele poleceń find i przejść przez katalog jest niepotrzebnych.

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

Po zapisaniu i utworzeniu pliku wykonywalnego możesz wywołać ten skrypt za pomocą polecenia find, jak poniżej.

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

Nie musisz się martwić ustawieniem opcji newermt dla find, ponieważ wszystko, co zapewnia, to pojedyncze wykonanie dla każdego znalezionego pliku, a skrypt podejmuje wszystkie decyzje.

Należy pamiętać, że jeśli nie wybierzesz -type, spowoduje to przenoszenie katalogów i prawdopodobnie spowoduje problemy. Możesz także użyć -type d, jeśli chcesz przenieść tylko katalogi. Brak ustawienia tego typu prawie na pewno spowoduje niepożądane zachowanie.

Pamiętaj, że ten skrypt został dostosowany do moich potrzeb. Możesz po prostu użyć mojej konstrukcji jako inspiracji do lepszego dopasowania do skryptu potrzeb. Dziękuję Ci!

Rozważania: Wydajność polecenia może być WIELKIE poprawiona, umożliwiając nieograniczoną liczbę argumentów przechodzących przez skrypt. Jest to w rzeczywistości stosunkowo łatwe, jeśli pominiesz zmienną $ @. Rozszerzenie tej funkcjonalności pozwoliłoby nam na przykład użyć funkcji find -exec + lub dźwigni xargs. Mogę to szybko wdrożyć i poprawić własną odpowiedź, ale to dopiero początek.

Ponieważ była to krótka sesja skryptowa, prawdopodobnie można wprowadzić wiele ulepszeń. Powodzenia!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.