Lista plików posortowana według liczby zawartych w nich linii

32

Jak mogę wyświetlić liczbę linii w plikach /group/book/four/word, posortowaną według liczby linii, które zawierają?

ls -l polecenie wyświetla je w dół, ale ich nie sortuje

Ken R.
źródło
1
Czy chcesz, aby pliki były wymienione według liczby wierszy, czy podaj liczbę wierszy w plikach, czy oba? ls -lnie podaje liczby linii. ls -lSsortuje plik według rozmiaru za pomocą niektórych lsimplementacji ( rozmiar jest liczbą bajtów w treści).
Stéphane Chazelas

Odpowiedzi:

34

Powinieneś użyć następującego polecenia:

find /group/book/four/word/ -type f -exec wc -l {} + | sort -rn
  • find: wyszukaj pliki na wybranej ścieżce. Jeśli nie chcesz, aby był rekurencyjny, a twoja findimplementacja go obsługuje, powinieneś dodać -maxdepth 1tuż przed -execopcją.
  • exec: nakazuje wykonanie polecenia dla wc -lkażdego pliku.
  • sort -rn: sortuj wyniki numerycznie w odwrotnej kolejności. Od większego do niższego.

(przy założeniu, że nazwy plików nie zawierają znaków nowej linii).

Jherran
źródło
Zauważ, że po przekazaniu więcej niż jednego pliku (lub w przypadku niektórych implementacji, więcej niż jednego pliku, który może odczytać), wcrównież wydrukuje totalwiersz, więc tutaj otrzymasz również jeden lub więcej „łącznych” wierszy, chyba że jest tylko jeden plik . Możesz potokować, aby grep /je usunąć.
Stéphane Chazelas
głosowanie za sortkomendą
Francisco
jak mogę filtrować, aby wyświetlać tylko plik z minimum X linii (wyklucz przykład X = 0 dla przykładu)?
Matryca
11

Brak rekurencji

Prawdopodobnie najprostsza wersja, jeśli nie potrzebujesz rekurencyjności:

wc -l /group/book/four/word/*|sort -n

wczlicza linie (opcja -l) w każdym (ale ukrytym) ( *) pliku poniżej /group/book/four/word/i sortsortuje wynik (przez potok |) numerycznie (opcja -n).

Rekurencyjne

Ktoś skomentował tę odpowiedź, wspominając o niej grep -rlc, zanim ją stłumi. Rzeczywiście grepjest świetną alternatywą, szczególnie jeśli potrzebujesz rekurencyjności:

grep -rc '^' /group/book/four/word/|tr ':' ' '|sort -n -k2

policzy (opcja -c) rekurencyjnie (opcja -r) wiersze pasujące ( grep) '^'(czyli początek linii) w katalogu /group/book/four/word/. Następnie musisz zastąpić dwukropek spacją, np. Używając tr, aby pomóc sort, którą chcesz posortować numerycznie (opcja -n) w drugiej kolumnie (opcja -k2).

Aktualizacja: Zobacz komentarz Stephane'a na temat możliwych ograniczeń i tego, jak możesz się go pozbyć tr.

Skippy le Grand Gourou
źródło
3
grep -c .zlicza wiersze zawierające co najmniej jeden poprawny znak. Służy grep -c '^'do zliczania wszystkich linii (w przypadku niektórych grepimplementacji policzy także końcowe znaki po ostatniej nowej linii ). Należy pamiętać, że nie wszystkie grepimplementacje obsługują a, -ra zachowanie różni się między tymi, które to robią. Nie musisz tłumaczyć :s (dwukropka, nie średnika) na spacje dla sort. Po prostu użyj -t:. Zauważ, że przy założeniu, że nazwy plików nie zawierają :ani znaków pustych ani nowego wiersza.
Stéphane Chazelas
1
Dziękujemy za opublikowanie swojego nierekurencyjnego rozwiązania; Nie wiedziałem, że wcpodałem tak poręczną sumę, jeśli przejdziesz wiele ścieżek. Połączenie tej funkcjonalności z dziką kartą i potokiem sortjest naprawdę czyste.
Qcom,
7

Z zsh:

lines() REPLY=$(wc -l < $REPLY)
printf '%s\n' /group/book/four/word/*(.no+lines)

Definiujemy nową funkcję sortowania,lines która odpowiada liczbą wierszy w pliku. I używamy o+lineskwalifikatora glob, który wraz z n(do sortowania numerycznego) określa, w jaki sposób uporządkowane są wyniki globu. ( .dodany również w celu sprawdzenia zwykłych plików).

Nie zakłada to, jaki znak nazwy plików mogą zawierać inne niż pliki ukryte (te zaczynające się od .) są pomijane. Dodaj Dkwalifikator glob, jeśli chcesz.

Stéphane Chazelas
źródło
2
OP jest oznaczony bashtylko ...
l0b0
7
@ l0b0, co nie oznacza, że ​​następna osoba, która będzie tego potrzebować, również uruchomi bash.
terdon
4

Nie określasz, czy chcesz również pliki w podkatalogach /group/book/four/word. findRozwiązanie w odpowiedzi jherran będzie zejść do podkatalogów. Jeśli nie jest to potrzebne, zamiast tego użyj powłoki:

for file in ./*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

Jeśli twoje nazwy plików mogą zawierać znaki nowej linii, możesz użyć czegoś takiego:

for file in ./*; do 
    [ -f "$file" ] && 
        printf "%lu %s\0" "$(wc -l < "$file")" "$file"
done | sort -zn | tr '\0' '\n'

Wreszcie, jeśli zrobić chcą zejść do podkatalogów, można to wykorzystać w bash4 lub powyżej:

shopt -s globstar
for file in ./**/*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

Zauważ, że wersje bashwcześniejsze niż 4.3 podążały za dowiązaniami symbolicznymi, gdy rekurencyjnie schodziły do ​​drzewa katalogów (takich jak zsh„s tcsh***/*).

Ponadto wszystkie powyższe rozwiązania będą ignorować ukryte pliki (te, których nazwa zaczyna się od ., użyj, shopt -s dotglobaby je uwzględnić), a także zawierać liczbę wierszy dowiązań symbolicznych (czego findpodejście nie będzie).

terdon
źródło
Zauważ, że inne różnice w stosunku do rozwiązania jherran są takie, że twoje rozważy również dowiązanie symboliczne do zwykłych plików ( -xtype fw GNU find lub *(-.)w zsh) i pominie ukryte pliki.
Stéphane Chazelas
@ StéphaneChazelas dzięki, wyjaśnione. Dlatego %luw printf? O ile pamiętam, to oznacza długi dziesiętny bez znaku, czy to naprawdę konieczne? Dlaczego nie traktować liczby jako ciągu? Czy to robi różnicę?
terdon
2
Jeśli wyjście wc jest puste (na przykład dlatego, że pliku nie można odczytać), zostanie ono rozwinięte 0zamiast pustego ciągu, co jest nieco lepsze. Niektóre implementacje sortowania działają z liczbami całkowitymi bez znaku, niektóre z podpisanymi. %lubrzmi jak najbezpieczniejszy zakład, ale prawdopodobnie nie ma to znaczenia, jakbyś miał 2^31linie, które i tak potrwają wieki.
Stéphane Chazelas
1

Jeśli chcesz zainstalować fdnaprawdę szybką wyszukiwarkę plików napisaną w Rust (powinieneś ją zainstalować, i tak warto ją mieć)

fd --type=file . | xargs wc -l | sort -n

Zasadniczo fdwyświetla listę plików, xargs przekaże listę plików wc(oznacza liczbę słów, ale przekazanie -l spowoduje, że zliczą linie), a następnie posortowane od najmniejszej liczby wierszy do największej sort -n.

JustGage
źródło