2011-06-07 18:23:57 +0000 2011-06-07 18:23:57 +0000
152
152

Unix/Linux znajdź i posortuj według daty modyfikacji

Jak mogę zrobić prosty find, który uporządkowałby wyniki według ostatnio zmodyfikowanych?

Oto obecny find, którego używam (robię ucieczkę z powłoki w PHP, więc to jest powód dla zmiennych):

find '$dir' -name '$str'\* -print | head -10

Jak mógłbym to uporządkować wyszukiwanie według ostatnio zmodyfikowanych? (Zauważ, że nie chcę, aby sortował ‘po’ wyszukiwaniu, ale raczej znajdował wyniki na podstawie tego, co zostało ostatnio zmodyfikowane).

Odpowiedzi (17)

168
168
168
2013-02-05 13:31:01 +0000

Użyj tego:

find . -printf "%T@ %Tc %p\n" | sort -n

printf argumenty z man find :

  • %Tk: Czas ostatniej modyfikacji pliku w formacie określonym przez k.

  • @: sekundy od Jan. 1, 1970, 00:00 GMT, z częścią ułamkową.

  • c: data i czas locale (Sat Nov 04 12:02:33 EST 1989).

  • %p: Nazwa pliku.

85
85
85
2011-06-07 18:39:34 +0000

Najprostszą metodą jest użycie zsh, dzięki jego kwalifikatorom globali .

print -lr -- $dir/**/$str*(om[1,10])

Jeśli masz GNU find, każ mu wypisywać czasy modyfikacji plików i sortować według tego.

find -type f -printf '%T@ %p```
find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^]* //' | head -n 10
```' |
sort -zk 1nr |
sed -z 's/^[^]* //' | tr '```
find . -type f -print |
perl -l -ne '
    $_{$_} = -M; # store file age (mtime - now)
    END {
        $,="\n";
        @sorted = sort {$_{$a} <=> $_{$b}} keys %_; # sort by increasing age
        print @sorted[0..9];
    }'
```' '\n' | head -n 10

Jeśli masz GNU find, ale nie inne narzędzia GNU, używaj nowych linii jako separatorów zamiast zer; stracisz obsługę nazw plików zawierających nowe linie.

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in (sorted(times.iterkeys(), key=lambda f:times[f], reverse=True))[:10]: print f'

Jeśli masz Perla (tutaj zakładam, że nie ma nowych linii w nazwach plików):

0x1&

Jeśli masz Pythona (również zakładając brak nowych linii w nazwach plików):

0x1&

Prawdopodobnie jest sposób na zrobienie tego samego w PHP, ale go nie znam.

Jeśli chcesz pracować tylko z narzędziami POSIX, jest to raczej bardziej skomplikowane; zobacz Jak rekurencyjnie wypisać pliki posortowane według daty modyfikacji (nie ma dostępnego polecenia stat!) (retatowanie pierwszych 10 to łatwa część).

41
41
41
2011-06-16 18:11:00 +0000

Nie musisz znać PHP ani Pythona, wystarczy ls :

man ls:
-t sort by modification time
-r, reverse order while sorting (--reverse )
-1 list one file per line

find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;

Jeśli polecenie zakończy pracę ze statusem niepowodzenia (tzn. Lista argumentów za długa ), to możesz iterować za pomocą find. Sparafrazowane z: Maksymalna długość argumentów dla nowego procesu

  • find . -print0|xargs -0 command (optymalizuje prędkość, jeśli find nie implementuje “-exec +”, ale zna “-print0”)
  • find . -print|xargs command (jeśli nie ma białej przestrzeni w argumentach)

Jeśli większa część argumentów składa się z długich, bezwzględnych lub względnych ścieżek, to spróbuj przenieść swoje działania do katalogu: cd /directory/with/long/path; command * A inną szybką poprawką może być dopasowanie mniejszej ilości argumentów: command [a-e]*; command [f-m]*; ...

10
10
10
2012-05-18 07:58:06 +0000

Potrzebujesz tylko ls

Możesz zrobić find /wherever/your/files/hide -type f -exec ls -1rt "{}" +; jak podano powyżej,

lub

ls -1rt `find /wherever/your/file/hides -type f`
```.
8
8
8
2014-04-24 08:12:01 +0000

Rozszerzając odpowiedź user195696’s answer :

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

Dla każdego pliku, to najpierw wyprowadza numeryczny znacznik czasu (do sortowania według, a następnie tabulacji \t), następnie czytelny dla człowieka znacznik czasu, następnie rozmiar pliku (niestety find nie może zrobić w mebibajtach, tylko kibibajtach), a następnie nazwę pliku ze względną ścieżką.

Następnie -printf sortuje je według pierwszego pola numerycznego.

Następnie sort -n pozbywa się pierwszego pola numerycznego, które nie jest interesujące dla użytkownika. (Drukuje drugie pole i kolejne.) Domyślnym separatorem pól jest cut lub tabulacja.

Przykład wyjścia:

Thu 06 Feb 2014 04:49:14 PM EST 64 KiB ./057_h2_f7_10/h2_f7_10.class
Fri 07 Feb 2014 02:08:30 AM EST 7962976 KiB ./056_h2_f7_400/h2__rh_4e-4.mph
Fri 07 Feb 2014 02:23:24 AM EST 7962976 KiB ./056_h2_f7_400/h2_f7_400_out_Model.mph
Fri 07 Feb 2014 02:23:24 AM EST 0 KiB ./056_h2_f7_400/h2_f7_400_out.mph.status
Fri 07 Feb 2014 02:23:24 AM EST 64 KiB ./056_h2_f7_400/1579678.out
Fri 07 Feb 2014 03:47:31 AM EST 8132224 KiB ./057_h2_f7_10/h2__rh_1e-5.mph
Fri 07 Feb 2014 04:00:49 AM EST 8132224 KiB ./057_h2_f7_10/h2_f7_10_out_Model.mph
Fri 07 Feb 2014 04:00:49 AM EST 0 KiB ./057_h2_f7_10/h2_f7_10_out.mph.status
Fri 07 Feb 2014 04:00:49 AM EST 64 KiB ./057_h2_f7_10/1579679.out
Fri 07 Feb 2014 09:47:18 AM EST 9280 KiB ./056_h2_f7_400/h2__rh_4e-4.mat
Fri 07 Feb 2014 10:51:23 AM EST 9728 KiB ./018_bidomain/h2_plain__rh_1e-5.mat
Fri 07 Feb 2014 10:58:33 AM EST 9568 KiB ./057_h2_f7_10/h2__rh_1e-5.mat
Fri 07 Feb 2014 05:05:38 PM EST 64 KiB ./058_h2_f7_stationary/h2_f7_stationary.java
Fri 07 Feb 2014 06:06:29 PM EST 32 KiB ./058_h2_f7_stationary/slurm.slurm
Sat 08 Feb 2014 03:42:07 AM EST 0 KiB ./058_h2_f7_stationary/1581061.err
Sat 08 Feb 2014 03:42:14 AM EST 64 KiB ./058_h2_f7_stationary/h2_f7_stationary.class
Sat 08 Feb 2014 03:58:28 AM EST 70016 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mph
Sat 08 Feb 2014 04:12:40 AM EST 70304 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mph
Sat 08 Feb 2014 04:12:53 AM EST 70304 KiB ./058_h2_f7_stationary/h2_f7_stationary_out_Model.mph
Sat 08 Feb 2014 04:12:53 AM EST 0 KiB ./058_h2_f7_stationary/h2_f7_stationary_out.mph.status
Sat 08 Feb 2014 04:12:53 AM EST 32 KiB ./058_h2_f7_stationary/1581061.out
Mon 10 Feb 2014 11:40:54 AM EST 224 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mat
Mon 10 Feb 2014 11:42:32 AM EST 224 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mat
Mon 10 Feb 2014 11:50:08 AM EST 32 KiB ./plot_grid.m

Celowo uczyniłem pole filesize 6 znakowym, ponieważ przy jego wydłużeniu staje się trudno wizualnie rozróżnić jak duże są pliki. W ten sposób pliki większe niż 1e6 KiB wyróżniają się: o 1 znak oznacza 1-9 GB, o 2 znaki oznacza 10-99 GB, itd.


Edycja: tutaj jest inna wersja (ponieważ \t zawiesza się na MinGW/MSYS):

find . -type f -printf "%T@\t%p\n" | sort -n | cut -f 2- | xargs -I{} ls -Glath --si {}

Daje wyjście jak:

-rw-r--r-- 1 es 23K Jul 10 2010 ./laptop_0000071.jpg
-rw-r--r-- 1 es 43M Jul 29 19:19 ./work.xcf
-rw-r--r-- 1 es 87K Jul 29 20:11 ./patent_lamps/US Patent 274427 Maxim Lamp Holder.jpg
-rw-r--r-- 1 es 151K Jul 29 20:12 ./patent_lamps/Edison screw-in socket.png
-rw-r--r-- 1 es 50K Jul 29 20:13 ./patent_lamps/1157 Lamp.jpg
-rw-r--r-- 1 es 38K Jul 29 20:14 ./patent_lamps/US06919684-20050719-D00001.png

Gdzie:

  • find . -printf "%Tc" powoduje, że wystąpienie -I{} jest zastępowane przez argument, a nowe linie są teraz separatorami argumentów (zauważ spacje w nazwach plików powyżej).

  • {} wyłącza wypisywanie nazwy grupy (marnowanie miejsca).

  • ls -G tworzy rozmiary plików czytelne dla człowieka (bardziej poprawne z ls -h --si).

  • --si sortuje według czasu, co nie ma tu znaczenia, ale ja właśnie tego zwykle używam.

4
4
4
2016-02-24 15:18:34 +0000

Wariant OS X odpowiedzi @user195696:

  1. z timestampem:

  2. Bez znacznika czasu:

2
2
2
2019-03-12 19:32:27 +0000

Mam proste rozwiązanie, które działa zarówno dla FreeBSD (OS X) jak i Linuksa:

find . -type f -exec ls -t {} +
2
2
2
2012-07-26 07:42:44 +0000

Odkryłem, że to załatwia sprawę na Mac OS X (i jest na tyle ogólne, że działa również na innych Unixenach):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort
1
1
1
2013-12-08 09:14:14 +0000

Użyj:

find . -type f -mtime 0 -printf "[%TD %TI:%TM%Tp] %s %p\n" | sort -n | awk '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

To polecenie posortuje pliki według daty modyfikacji.

I wyświetli się jak:

[12/05/13 03:10PM] 1.75 MB ./file.text
[12/06/13 11:52PM] 2.90 MB ./file2.mp4
[12/07/13 04:11PM] 4.88 MB ./file3.mp4
[12/07/13 09:17PM] 4.74 MB ./test.apk
1
1
1
2014-05-02 11:16:59 +0000

Jeśli twój wybór find jest bardzo prosty, możesz być w stanie obejść się bez niego i po prostu użyć ls:

ls -1 *.cc # -r -t optional
0
0
0
2014-07-04 14:58:50 +0000

Poprawiłem odpowiedź Akashs, sprawiając, że skrypt poprawnie obsługuje białe spacje w nazwach plików:

find . -type f -mtime 0 -printf ";[%TD %TI:%TM%Tp];%s;%p\n" | sort -n | awk -F ";" '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';
0
0
0
2019-09-11 08:23:43 +0000

Istnieje czysty i solidny sposób na sort | head według daty:

Użycie ls -l do ładnego drukowania

find . ! -type d -printf "%T@ %p```
findByDate() {
    local humansize=''
    ["$1" = "-h"] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p```
Usage: findByDate [-h] [lines] [find options]
```" |
        sort -zrn |
        head -zn ${1:--0} |
        sed -z 's/^[0-9.] //' |
        xargs -0 ls -dlt${humansize}
}
```" |
    sort -zrn |
    head -zn 10 |
    sed -z 's/^[0-9.] //' |
    xargs -0 ls -lt

Jako funkcja bash :

findByDate

This could by run with one or two argument, or even without:

findByDate -h 12

Przykład:

findByDate 42 '-type l'

Will list all non directories sorted by date. Uwaga:

Nawet na dużym drzewie systemu plików, ponieważ xargs otrzymuje już posortowaną listę, kolejność plików pozostaje poprawna, nawet jeśli ls musi być uruchamiany wiele razy.

findByDate -0 '( -type l -o -type b -o -type s -o -type c )'

Wylistuje 12 kolejnych rekursywnych niekatalogów posortowanych według daty, z rozmiarem wypisanym w _czytelnej dla człowieka formie

findByDate() {
    local humansize=''
    ["$1" = "-h"] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p```
Usage: findByDate [-h] [lines] [find options]
```" |
        sort -zn |
        tail -zn ${1:-+0} |
        sed -z 's/^[0-9.] //' |
        xargs -0 ls -dltr${humansize}
}

Wylistuje 42 kolejne rekursywne symlinki

0x1&

Wylistuje wszystkie symlinki, urządzenia blokowe, gniazda i urządzenia znakowe, posortowane według daty.

Odwrócenie kolejności

Zamiana head na tail i zamiana przełącznika sort i ls:

0x1&

Ta sama funkcja, to samo zastosowanie:

0x1&.

0
0
0
2011-06-07 18:33:10 +0000

Nie wydaje mi się, żeby find miał jakiekolwiek opcje modyfikacji porządku na wyjściu. -mtime i -mmin pozwolą Ci ograniczyć wyniki do plików, które zostały zmodyfikowane w określonym przedziale czasu, ale wyjście nie będzie posortowane - będziesz musiał zrobić to sam. GNU find posiada opcję -printf, która, między innymi, pozwoli Ci wypisać czas modyfikacji każdego znalezionego pliku (łańcuchy formatu %t lub %Tk) ; może to pomóc Ci posortować wyjście find tak, jak chcesz.

0
0
0
2018-06-24 23:33:20 +0000

Możesz użyć stat na BSD i Linuksie (nie na POSIX) w ten sposób:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | cut -f2-

Jeśli chcesz ograniczyć liczbę:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | head -[the number] | cut -f2-
```.
0
0
0
2014-05-17 10:55:57 +0000

Jeśli chcesz zamówić wszystkie pliki PNG według czasu w $PWD:

Ten prosty one-liner daje całą elastyczność regexp na find i na ls.

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less
-1
-1
-1
2017-03-28 01:13:40 +0000

Jeśli chcesz tylko uzyskać pełną ścieżkę do każdego elementu, możesz zapisać w ten sposób.

find FIND_ROOT -maxdepth 1 -type f -printf "%T@ %p\n" | sort -nr | head -10 | cut -d ' ' -f 2

Gdzie -printf “%T@ %p\n ” dla podania kryteriów sortowania (data), ‘sort -nr’ dla sortowania według daty, head -10 dla wypisania 10 najlepszych wyników, cut -d ‘ ’ -f 2 dla obcięcia wiodącego timestampa w każdej linii.

-3
-3
-3
2017-03-25 09:09:59 +0000

Mam proste rozwiązanie.

Po cd do katalogu, użyj

find . -iname "*" -ls