jak sprawdzić w bash, czy plik został utworzony więcej niż x razy temu?

106

Chcę sprawdzić w linux bash, czy plik został utworzony więcej niż x razy temu.

powiedzmy, że plik nazywa się text.txt, a czas to 2 godziny.

 if [ what? ]
 then
     echo "old enough"
 fi
Lecieć jak po sznurku
źródło

Odpowiedzi:

139

Tylko na czas modyfikacji

if test `find "text.txt" -mmin +120`
then
    echo old enough
fi

Możesz użyć -cmindo zmiany lub -aminczasu dostępu. Jak wskazywali inni, nie sądzę, aby można było śledzić czas tworzenia.

kmkaplan
źródło
3
możesz porzucić „test” i znaki grawitacyjne. Jest to analogiczne do 'if (test == true)' vs 'if (test)'
guns
2
Masz rację; Przypuszczam, że myślałem, że findzwraca wartość niezerową, gdy nie znaleziono żadnych dopasowań.
działa
4
Możesz upuścić lewe znaczniki i zrobić, jeśli test $ (znajdź tekst.txt -mmin +120)
tommy.carstensen
1
@BroSlow wygląda lepiej: nie ma możliwości „więcej niż jednego”. Oczywiście text.txtzakłada się , że nie jest to katalog.
kmkaplan,
2
Wolę tę składnię:[ "$(find path/to/file -mmin +120)" ] && echo "it is old"
Alfe
42

Zawsze lubiłem używać, date -r /the/file +%saby znaleźć swój wiek.

Możesz również zrobić touch --date '2015-10-10 9:55' /tmp/filebardzo drobnoziarnisty czas w dowolnej dacie / godzinie.

nemik
źródło
Szukałem dzisiaj tego samego. Najlepsza!
Umair A.
Dzięki. Wylądowałem na tym SO pytaniu, ponieważ wyszukałem w Google „jak wydrukować wiek pliku bash”. Więc to jest dokładnie to, czego szukałem!
Noah Sussman
5
Dzięki! z zastrzeżeniem, że tylko powyżej jest znacznik czasowy (nie wiek), ale mogą być używane do calc wiek, tak jak let AGE=$(($(date +%s)-$(date -r /path/to/file +%s))) [przy założeniu, że tworzone i nie modyfikowane lub „wiek względnej mod”]
nhed
function file-age { FILE_CREATED_TIME=`date -r "$1" +%s`; TIME_NOW=`date +%s`; echo "$[ ${TIME_NOW} - ${FILE_CREATED_TIME} ]"; }
turiyag
1
@turiyag Obowiązkowa uwaga, która $[ ], jeśli nie jest przestarzała , to przynajmniej stara i mniej przenośna , a $(( ))zamiast tego należy użyć ; a cytaty wsteczne są bardziej kruche niż $( ); a także łączniki w nazwach funkcji mogą nie być w pełni przenośne. Jednak istota tego jest dobra!
michaelb958 - GoFundMonica
23

Korzystając z, stataby ustalić datę ostatniej modyfikacji pliku, dateokreślić aktualny czas i liberalne użycie bashizmów, można przeprowadzić test, który chcesz, na podstawie czasu ostatniej modyfikacji pliku 1 .

if [ "$(( $(date +"%s") - $(stat -c "%Y" $somefile) ))" -gt "7200" ]; then
   echo "$somefile is older then 2 hours"
fi

Chociaż kod jest nieco mniej czytelny niż findpodejście, myślę, że jest to lepsze podejście niż bieganie w findcelu przejrzenia pliku, który już „znalazłeś”. Poza tym manipulowanie datami jest fajne ;-)


  1. Jak Phil słusznie zauważył, czas tworzenia nie jest rejestrowany, ale użyj go %Zzamiast %Yponiżej, aby uzyskać „czas zmiany”, który może być tym, czego chcesz.

[Aktualizacja]

W przypadku użytkowników komputerów Mac użyj stat -f "%m" $somefilezamiast powyższej składni specyficznej dla systemu Linux

Guss
źródło
W jakiej powłoce wbudowana jest data i statystyka? Mój bash (GNU, 3.2.48) ich nie ma.
Ian Clelland
UPS przepraszam. statnie jest wbudowany - bardzo źle ze mnie, naprawię.
Guss
1
@Guss właściwym rozwiązaniem jest instalacja coretutils z naparem. :-)
Erik Johansson
1
@ErikJohansson Wolę nie wymagać instalacji dodatkowego oprogramowania, gdy używanie istniejącego działa dobrze - to nie jest Windows, wiesz ;-)
Guss
1
Dla osób, które chcą tego używać, ale modyfikują, dobrze byłoby wiedzieć dokładnie, co robi: $ (($ (data + "% s") - sekundy od 1970-01-01 00:00:00 UTC (Epoka) $ (stat -c "% Y" $ jakiś plik))) - Czas ostatniej modyfikacji w sekundach od Epoki -gt "7200" - sprawdza czy różnica jest większa niż x liczba sekund.
devo
16

Czas utworzenia nie jest przechowywany.

Przechowywane są trzy znaczniki czasu (generalnie można je wyłączyć na niektórych systemach plików lub za pomocą pewnych opcji systemu plików):

  • Czas ostatniego dostępu
  • Czas ostatniej modyfikacji
  • Czas ostatniej zmiany

„Zmiana” w pliku jest liczona jako zmiana uprawnień, zmiana nazwy itp. Podczas gdy modyfikacja dotyczy tylko zawartości.

Philip Reynolds
źródło
12

Chociaż ctime nie jest technicznie czasem tworzenia, dość często nim jest.

Ponieważ ctime nie mają na niego wpływu zmiany zawartości pliku, zwykle jest on aktualizowany tylko podczas tworzenia pliku. I tak - słyszę, jak wszyscy krzyczysz - jest również aktualizowany, jeśli zmienisz uprawnienia dostępu lub własność ... ale ogólnie jest to coś, co robi się raz, zwykle w tym samym czasie, gdy umieszczasz tam plik.

Osobiście zawsze używam mtime do wszystkiego i wyobrażam sobie, że tego właśnie chcesz. Ale w każdym razie ... oto powtórka „nieatrakcyjnego” basha Gussa w łatwej w użyciu funkcji.

#! / bin / bash
function age () {
   lokalna nazwa pliku = $ 1
   lokalna zmiana = `stat -c% Y" $ filename "` `
   local now = `date +% s`
   lokalny upłynął

   let elapsed = teraz-zmienione
   echo $ minęło
}

plik = „/”
echo Wiek pliku $ file wynosi $ (wiek "$ file") sekund.
Maryam Jeddian
źródło
Było to przydatne, ale nie działało od razu na OSX, ponieważ statystyka jest na nim implementowana inaczej. Jedynym sposobem zgodnym z różnymi systemami, jaki znalazłem, było użycie perla. Skrypt powinien działać na komputerach Mac, jeśli local changed=$(perl -MFile::stat -e "print stat(\"${filename}\")->mtime")
zastąpisz
1
„Czas tworzenia” to pojęcie trudne do zrozumienia. Co to oznacza dla skopiowanego pliku? Co z przeniesionym plikiem? A co by było, gdyby został przeniesiony przez granicę urządzenia (więc w pewnym sensie powstał od nowa)? Co to oznacza dla spakowanego i później rozpakowanego pliku? Możliwych jest kilka odpowiedzi i nie ma konsensusu. Wspomnienie o ctime jest jednak miłe, ale nie ująłbym tego semantycznie blisko niejasnej koncepcji „czasu stworzenia”. Zwłaszcza, że ​​prosty chmod, zastosowany do pliku, unieważni ten pomysł. Ale mogę z tobą żyć ;-)
Alfe
@Alfe: Brakuje ci +%sdrugiej połowy
Grizly
Ten wiek może być znacznie krótszy: age() { echo $(( $(date +%s) - $(date -r "$1" +%s) )); } (Dzięki @Grizly za korektę!)
Alfe
Właściwie lepiej jest użyć czasu dostępu, który jest czasem utworzenia na wszystkich systemach plików zamontowanych z noatimeopcją (co jest dobre dla wydajności, więc powinieneś go używać). Więc po prostu użyj %Xzamiast %Y.
Nux
7

Znajdowanie jest dobre, ale myślę, że możesz użyć innego sposobu, zwłaszcza jeśli potrzebujesz teraz, ile sekund jest stary plik

date -d "now - $( stat -c "%Y" $filename ) seconds" +%s

używając daty GNU

Porównaj
źródło
użyj gstat, „brew install coreutils”
Erik Johansson,
3

Rozważ wynik narzędzia „stat”:

  File: `infolog.txt'
  Size: 694         Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 11635578    Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/     fdr)   Gid: ( 1000/     fdr)
Access: 2009-01-01 22:04:15.000000000 -0800
Modify: 2009-01-01 22:05:05.000000000 -0800
Change: 2009-01-01 22:05:05.000000000 -0800

Możesz zobaczyć tutaj trzy daty dostępu / modyfikacji / zmiany. Nie ma daty utworzenia. Możesz być naprawdę pewien tylko, kiedy zawartość pliku została zmodyfikowana (pole „modyfikuj”) lub zmienił się jego i-węzeł (pole „zmiana”).

Przykłady sytuacji, gdy oba pola są aktualizowane:

„Modyfikuj” zostanie zaktualizowane, jeśli ktoś połączy dodatkowe informacje na końcu pliku.

„Zmiana” zostanie zaktualizowana, jeśli ktoś zmieni uprawnienia przez chmod.

fdr
źródło
przyznane, statystyka może podać istotne informacje. Ale analiza w celu uzyskania tego, czego chcemy, będzie dość żmudna.
PypeBros
0

używam

file_age() {
    local filename=$1
    echo $(( $(date +%s) - $(date -r $filename +%s) ))
}

is_stale() {
    local filename=$1
    local max_minutes=20
    [ $(file_age $filename) -gt $(( $max_minutes*60 )) ]
}

if is_stale /my/file; then
    ...
fi
xpmatteo
źródło