Jak wyświetlić listę plików starszych niż jeden dzień z „2015” w nazwie pliku?

11

Chcę wymienić wszystkie pliki dziennika, które nie należą do dzisiaj, i tylko pliki, które zawierają 2015ich nazwy.

Oto polecenia, które wypróbowałem:

find . -name 2015 -mtime +1 -exec  ls -ltrh  {} \;
find . -name *2015* -mtime +1 -exec  ls -ltrh  {} \;

Dane wyjściowe z obu są niczym, ale nadal istnieją pliki. Coś jest nie tak z tymi poleceniami i nie rozumiem co. Każda pomoc będzie mile widziana.

rɑːdʒɑ
źródło
findCzęść wygląda dobrze dla mnie, ale ja też miałem problemy z -execparametrem. Nie mogłem też tego uruchomić. (Próbowałem przenieść wszystkie pliki jpg z jednego folderu do jego katalogu nadrzędnego - i ostatecznie zrobiłem to ręcznie ...)
Byte Commander
2
Możesz rzucić
steeldriver
@steeldriver Wydaje mi się, że tak naprawdę dzieje się tutaj źle, ponieważ jeśli w bieżącym katalogu byłyby pliki z 2015ich nazwami (inna oczywista wada sposobu pisania polecenia), podejrzewam, że pojawiłby się jakiś wynik. Więc możesz opublikować odpowiedź na ten temat.
Eliah Kagan

Odpowiedzi:

18

Polecenie find . -name '*2015*' -mmin +1440 -lsprawdopodobnie zrobi to, co chcesz. Szczegóły poniżej.

Twoje pierwsze polecenie miało -name 2015. Nie działało, ponieważ wyszukuje tylko pliki o dokładnie takich nazwach 2015, bez żadnych innych znaków.

Twoje drugie polecenie find . -name *2015* -mtime +1 -exec ls -ltrh {} \;mogło się nie powieść z kilku powodów:

1. Niecytowane *znaki są rozszerzane przez powłokę, a następnie przekazywane do find.

Jeśli w bieżącym katalogu znajdują się pliki (w tym, w którym uruchomiłeś tę find ...komendę), których nazwy zawierają 2015(i nie zaczynają się na a .), powłoka została rozwinięta *2015*do listy nazw plików, a następnie przekazana ta lista jako argumenty find. To nie jest to, czego chcesz - zamiast tego chcesz przekazać *2015*dosłownie jako argument do znalezienia, aby find, a nie powłoka, mogła znaleźć, które pliki pasują do niego.

Aby rozwiązać ten problem, cytat *2015*. Istnieją trzy popularne sposoby:

  • '*2015*'(tj. find . -name '*2015*' -mtime +1 -exec ls -ltrh {} \;)
  • "*2015*"(tj. find . -name "*2015*" -mtime +1 -exec ls -ltrh {} \;)
  • \*2015\*(tj. find . -name \*2015\* -mtime +1 -exec ls -ltrh {} \;)

I sugeruję pisanie go z apostrofami jak '*2015*', ponieważ:

Ale w tym przypadku tak naprawdę nie ma to znaczenia. 'i "oba traktują *to samo, a wyrażenie nie jest wystarczająco skomplikowane do \cytowania, aby utrudnić zrozumienie.

2. -mtime +1wybiera tylko pliki zmodyfikowane dwa lub więcej dni temu.

Jak man findmówi:

       Numeric arguments can be specified as

       +n     for greater than n,

       -n     for less than n,

       n      for exactly n.
       -mtime n
              File's data was last modified n*24 hours ago.  See the  comments
              for -atime to understand how rounding affects the interpretation
              of file modification times.
       -atime n
              File was last accessed n*24 hours ago.  When  find  figures  out
              how  many  24-hour  periods  ago the file was last accessed, any
              fractional part is ignored, so to match -atime +1, a file has to
              have been accessed at least two days ago.

Załóżmy, że plik został zmodyfikowany 47 godzin temu. Aby dowiedzieć się, ile to jest 24-godzinnych okresów, findzaokrągla się w dół : jest to jeden okres 24-godzinny. Ale -mtime +1pasuje tylko do plików, których czasy modyfikacji są ściśle dłuższe niż jeden 24-godzinny okres temu. W związku z tym pliki z wczoraj nie są dopasowane.

Zobacz, dlaczego funkcja find -mtime +1 zwraca tylko pliki starsze niż 2 dni? po więcej informacji, jak sugeruje steeldriver .

Aby znaleźć pliki ostatnio zmodyfikowano każdej chwili więcej niż 24 godziny temu , proponuję zamiast określające go jako 1440 minut temu z -mmin +1440:

find . -name '*2015*' -mmin +1440 -exec ls -ltrh {} \;

Niektórzy czytelnicy mogą się zastanawiać, dlaczego nie cytowałem {}. Niektórzy cytują, {}aby przypomnieć ludziom, że nie jest to wyrażenie na rozwijanie nawiasów klamrowych . Pociski w stylu Bourne'a (jak bash ) nie wymagają {}cytowania. Może jakaś powłoka nie w stylu Bourne'a traktuje ją specjalnie; dlatego niektórzy użytkownicy mogą to zacytować. Istnieje jednak błędne przekonanie, że czasami trzeba cytować, {}aby -execpoprawnie traktować nazwy plików ze spacjami. Że; s fałsz: z {}lub '{}', finddostaje takie same argumenty, jak skorupa usuwa cytaty przed przejściem '{}'dofind. Aby przeciwdziałać temu nieporozumieniu, nie cytuję {}, ale jest to kwestia stylu - jeśli wolisz {}dokumentować, w jaki sposób powłoka nie traktuje, {a }specjalnie, to w porządku.

Polecam również albo zmienić lspolecenie, lub (jak muru zasugerował ) zastąpić go find„s -lsdziałania. ls -ltrhprawdopodobnie nie robi tego, co zamierzasz, ponieważ jest uruchamiany osobno dla każdego znalezionego pliku, a zatem flagi -ti -r, które określają sortowanie, są nieistotne.

Chociaż dane wyjściowe zostaną sformatowane nieco inaczej niż przy ls -lużyciu, użycie -lsjest prostsze i łatwiejsze.

find . -name '*2015*' -mmin +1440 -ls

Lub jeśli zdecydujesz, że naprawdę potrzebujesz tylko wymienić nazwy pliku (w tym ich ścieżki, w stosunku do .), możesz po prostu określić brak akcji, co spowoduje -printużycie domyślnej akcji:

find . -name '*2015*' -mmin +1440
Eliah Kagan
źródło
1
Ładna, dokładna odpowiedź! przynajmniej przy GNU find istnieje też newerXYskładnia, która akceptuje argumenty kalendarza np. -newermt 'yesterday'i! -newermt 'yesterday'
steeldriver
Wiesz co ? Jesteś niesamowity. @ Eliah Kagan
rɑːdʒɑ
Dzięki sterownikowi Stell, to bardzo dobra informacja z linku wiedzieć. Ale w moim przypadku, ponieważ jest to dziennik aplikacji z aplikacji, stare pliki nie miały możliwości modyfikacji. Dziękuję jeszcze raz
rɑːdʒɑ
2

Cytuj wyrażenie, a proponuję również zacytować nawiasy

find . -name "2015" -mtime +1 -exec  ls -ltrh  '{}' \;

lub

find . -name "*2015*" -mtime +1 -exec  ls -ltrh  '{}' \;

nie musisz przekazywać znalezionych plików do ls

find . -name "*2015*" -mtime +1
Pantera
źródło
Może ograniczyć używanie -type f? A jeśli lstrzeba użyć, sugeruj użycie -ls.
muru
1
jasne, wszystkie dobre sugestie. Nie jestem pewien, czego chce OP i uważam, że źródłem problemu jest brak cudzysłowów wokół wzorca wyszukiwania „-nazwa”.
Panther
2

W zsh możesz używać globalnych kwalifikatorów (jest to unikalna funkcja zsh, niedostępna w innych powłokach, takich jak bash).

ls -ltr *2015*(m+1)

Wyświetla tylko pliki w bieżącym katalogu; aby rekurencyjnie przeglądać katalogi , użyj

ls -ltr **/*2015*(m+1)

Dzięki find, -name 2015tylko wyszukuje pliki, których nazwa jest dokładnie 2015. -name *2015*działa tylko wtedy, gdy 2015w bieżącym katalogu nie ma plików, których nazwa zawiera , ponieważ powłoka rozwija wzorzec *2015*przed findwywołaniem. Musisz zacytować wzór:

find -name '*2015*' -mtime +1 …

Zauważ, że zarówno find -mtime +1i zsh *(m+1)znajdują pliki, które mają co najmniej 48 godzin , a nie pliki starsze niż dzisiaj. Znak plus oznacza „ściśle więcej niż”, a liczba dni jest zaokrąglana w dół. Aby znaleźć pliki, które mają co najmniej 24 godziny, użyj -mtime +0lub (m+0).

Jeśli chcesz znaleźć pliki, które zostały ostatnio zmodyfikowano wczoraj lub wcześniej , można skorzystać findz -newermtpredykatu :

find -name '*2015*' ! -newermt 'today 0:00' …

Nie ma naprawdę wygodnego sposobu na wykonanie tego testu w Zsh.

Gilles „SO- przestań być zły”
źródło