Posortuj dane wyjściowe find -exec ls

14

Czy możliwe jest wyjście find … -exec ls -ls ;posortowane alfabetycznie według nazwy pliku?

To jest moje polecenie crona:

find /home/setefgge/public_html -type f -ctime -1 -exec ls -ls {} \;

To polecenie działa w większości dobrze. Ale wyniki nie są sortowane w żadnej znaczącej kolejności. Byłoby bardzo pomocne, gdyby zostały posortowane według pola nazwy pliku.

MaJ
źródło
1
Używasz Zsh? ls -ls **/*(.)
Kevin
@Kevin Niezupełnie - lsposortuje.
Gilles „SO- przestań być zły”

Odpowiedzi:

14

Zakładam, że twoje nazwy plików nie zawierają nowych linii.

find /home/setefgge/public_html -type f -ctime -1 -exec ls -nls {} + | sort -k 10

Użycie +zamiast ;do zakończenia -execakcji powoduje, że jest szybsza poprzez grupowanie wywołań ls. Możesz sortować, przesyłając przez sortpolecenie; każ mu rozpocząć sortowanie od 10. pola (pierwsze 9 to metadane: bloki, uprawnienia, liczba linków, użytkownik, grupa, rozmiar i 3 pola daty / godziny). Ta opcja -nmówi lso użyciu wartości liczbowych dla użytkownika i grupy, co pozwala uniknąć ryzyka, że ​​nazwy użytkownika lub grupy zawierają spacje.

Alternatywnie, zsh, możesz uciec bez żadnego założenia przy użyciu jakiejkolwiek nazwy, używając kwalifikatorów glob do gromadzenia i sortowania plików oraz zargsuruchamiania lswielu razy, jeśli linia poleceń byłaby zbyt długa. Potrzebujesz GNU ls(konkretnie jego -fopcji), aby uniknąć ponownego sortowania według ls(innym podejściem byłoby emulowanie za lspomocą Zsh zstat).

autoload -U zargs
zargs -- /home/setefgge/public_html/**/*(.c-2) -- ls -lnsf
Gilles „SO- przestań być zły”
źródło
Dziękuję bardzo! Sortowanie odbywa się za pomocą pierwszego wysłanego polecenia. Czy liczba nadal wynosiłaby 10, jeśli wybiorę krótszą ścieżkę? Na przykład, jeśli uruchomię to samo polecenie z / home / setefgge zamiast z public_html?
MaJ
@ MaJ 10 to liczba pomijanych pól, nie ma to nic wspólnego z rozmiarem nazwy pliku.
Gilles 'SO - przestań być zły'
Dziękuję Ci. Doceniam twoją pomoc, a także pomoc udzieloną przez wszystkich innych. Uważam ten problem za rozwiązany. Moje polecenie cron sortuje teraz pliki. Po raz pierwszy zadałem pytanie Stackexchange. Nie widzę opcji „Rozwiązane”. Jeśli ktoś z was wie, jak opublikować to jako rozwiązane, prosimy o zrobienie tego. Dzięki!
MaJ
@MaJ Najbliższą rzeczą, którą musimy oznaczyć jako rozwiązane pytanie, jest oznaczenie jednej z odpowiedzi jako zaakceptowanych. Tylko ty, pytający, możesz to zrobić. Aby to zrobić, kliknij znacznik wyboru obok odpowiedzi, która najbardziej Ci pomogła. Jeśli zaakceptujesz odpowiedź, otrzymasz 2 dodatkowe punkty reputacji, a następnie będziesz mógł głosować na posty; możesz głosować za wszystkimi postami, które uważasz za pomocne. Aby uzyskać więcej informacji, zobacz stronę przewodnika i stronę pomocy na temat tego, kiedy ktoś odpowie na twoje pytanie .
Gilles „SO- przestań być zły”
1

Dlaczego nie potokować wyniku wyszukiwania przez sort, a następnie wykonać ls dla każdej linii?

find . -type f -ctime -1 | sort | while IFS= read -r filename; do ls -ls "$filename"; done
groxxda
źródło
1

POSIX ma do powiedzenia na temat dat na ls -lliście ong:

<date and time>Pole zawiera odpowiednią datę i znacznik czasu, kiedy plik był ostatnio modyfikowany. W ustawieniach narodowych POSIX, pole powinno odpowiadać wyjściu następującego polecenia date:

date "+%b %e %H:%M"

... jeśli plik został zmodyfikowany w ciągu ostatnich sześciu miesięcy lub:

date "+%b %e %Y"

Biorąc to pod uwagę i upewniając się, że jeśli w nazwie pliku znajdują się nowe wiersze, są one odpowiednio globowane za pomocą również ls -qopcji określonej w POSIX , stosunkowo łatwo jest przygotować wyrażenie regularne dla lswyniku bez find:

d=$(date "+%b %e") y=$(date --date=yesterday "+%b %e")
echo "$d" "$y"

###OUTPUT###
Jul  5 Jul  4

grepw tym celu zwracane będą tylko wiersze zawierające ciągi reprezentujące dzisiejsze lub wczorajsze daty. Następujące polecenie trochę to dodaje:

ls -alRcq | sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

ls opcje składają się z:

  1. -a zwróć wszystkie pliki w katalogu - w tym te, które zaczynają się na .dot
  2. -l długa lista
  3. -R rekurencyjnie wypisz wszystkie katalogi potomne
  4. -c wyświetla czas modyfikacji, a nie czas dostępu
  5. -qzwraca nazwę globu powłoki ?zamiast \tznaków niedrukowalnych lub znaków ab w nazwie pliku

Wyniki są przekazywane do |pipepliku, do sedktórego pasuje tylko:

  1. Pusty wiersz poprzedzający nazwę ścieżki i następujący wiersz
  2. Linie zaczynające się od - (innymi słowy - nie ddla katalogu), które również zawierają twój date.
  3. Nie drukuje jednak wierszy ścieżki, chyba że katalog, którego nazwa zawiera, zawiera pliki, które przefiltrowałeś.

Dane wyjściowe wyglądają następująco:

ls -alRcq --color=always | 
sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

###OUTPUT###
.:
-rw------- 1 mikeserv mikeserv   2086 Jul  4 10:52 .bash_history
-rw------- 1 mikeserv mikeserv   2657 Jul  4 15:20 .lesshst
-rw-r--r-- 1 mikeserv mikeserv    681 Jul  5 05:18 .zdirs
-rw------- 1 mikeserv mikeserv 750583 Jul  5 08:28 .zsh_history
-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 Terminology.log
-rw-r--r-- 1 mikeserv mikeserv 433568 Jul  4 13:34 shot-2014-06-22_17-10-16.jpg
-rw-r--r-- 1 mikeserv mikeserv 445192 Jul  4 13:34 shot-2014-06-22_17-11-06.jpg

./.cache/efreet:
-rw------- 1 mikeserv mikeserv  37325 Jul  4 22:51 desktop_localhost_C.eet
-rw------- 1 mikeserv mikeserv  37325 Jul  4 23:30 desktop_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 22:51 desktop_util_localhost_C.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 23:30 desktop_util_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  16037 Jul  4 23:30 icon_themes_localhost.eet
-rw------- 1 mikeserv mikeserv   3117 Jul  4 23:30 icons___efreet_fallback_localhost.eet
-rw------- 1 mikeserv mikeserv 768039 Jul  4 23:30 icons_gnome_localhost.eet
-rw------- 1 mikeserv mikeserv  18589 Jul  4 23:30 icons_hicolor_localhost.eet

./.config:
-rw-r--r-- 1 mikeserv mikeserv   30 Jul  4 19:10 pavucontrol.ini

./.config/chrome:
-rw-r--r-- 1 mikeserv mikeserv 94332179 Jul  4 13:36 conf.tar.lz4.bak

Tak, to nawet działa z LS_COLORS- co jest prawdopodobnie niskim priorytetem dla ciebie cron, ale, hej, twoje opcje są otwarte.

W każdym razie oferuje to pewne znaczące zalety w porównaniu z innymi możliwymi rozwiązaniami.

  1. Po pierwsze find+ lsobejmuje wiele wywołań - dotyczy to tylko jednego lsprocesu i dlatego jest w stanie niezawodnie sortować wszystko - co robi domyślnie - i dlatego sortjest również pomocniczy.

  2. Każde rozwiązanie obejmujące finda sorti lsjest dość dużo robi wszystko z pracy dwa razy. lsi findrozpozna każdą ścieżkę i statkażdy plik. lsi sortoba posortują wszystkie wyniki. Prawdopodobnie najlepiej jest po prostu użyć singla ls.

  3. Potem oczywiście są datei sedczęści tej odpowiedzi. Ważną rzeczą do zapamiętania jest to, że wykonujesz trudną część i najpierw otrzymujesz wyrażenie regularne - i tylko raz - a następnie przycinasz tylko jedną listę wyników, zamiast mówić, uzyskiwać wyniki, uzyskiwać wyniki, sortować wyniki i sortować wyniki.

  4. Nie wpływa to na nazwy plików zawierające znaki nowej linii, podobnie jak inne rozwiązania. To rozwiązanie ma swoje własne zastrzeżenia - które wyjaśnię dalej - ale są niewielkie i łatwe do rozwiązania. Moim zdaniem jest to najbardziej niezawodne rozwiązanie tutaj.

Istnieją dwa przypadki, w których powyższe polecenie może powodować problemy. Pierwszy dotyczy ?globów w nazwach plików - chociaż jest to już bardziej niezawodne rozwiązanie niż jakiekolwiek inne oferowane tutaj, a prawdopodobieństwo, że się ?w ogóle natkniesz, jest wystarczająco małe samo w sobie, istnieje możliwość rozwiązania tych globów może pasować do więcej niż jednej nazwy pliku. Zobacz to, aby uzyskać więcej informacji na ten temat.

Inna możliwość wiąże się z fałszywym pozytywem - na przykład jeśli masz nazwę pliku faktycznie pasującą do dateciągu, którego szukamy, grepale nie została ona faktycznie zmodyfikowana w żadnym z tych dni. Nie liczę na to, że jest to problem, ale jeśli tak, zapytaj o to i prawdopodobnie pomogę ci sprecyzować wyrażenie regularne, aby sobie z tym poradzić.

mikeserv
źródło
0

Możesz użyć kombinacji find, xargs i ls.

Oto przykładowe polecenie: find . -type f -print0 | xargs -0 ls -lt

  • find będzie rekurencyjnie szukał wszystkich plików w bieżącym katalogu.
  • xargs przekaże tę listę plików do lspolecenia w jednym wywołaniu (pod warunkiem, że findzwraca mniej niż ARG_MAXpliki).
  • ls -lt posortuje te pliki według czasu i sformatuje dane wyjściowe

Aby odzyskać system ARG_MAX, możesz wpisać:

$ getconf ARG_MAX
> 2621440
Max
źródło
-1
ls -l $(find /home/setefgge/public_html -type f -ctime -1 | sort)
Walter A.
źródło
1
lsdokonuje własnego sortowania, więc findprzepuszczanie danych wyjściowych przez sortprzelot jest bezużyteczne. Ponadto twoje polecenie zmienia nazwy plików zawierające spacje (między innymi) i zakończy się niepowodzeniem, jeśli będzie zbyt wiele nazw plików.
Gilles „SO- przestań być zły”