Jak uzyskać „wc -l”, aby wypisać tylko liczbę wierszy bez nazwy pliku?


155
wc -l file.txt

wyświetla liczbę linii i nazwę pliku.

Potrzebuję tylko samego numeru (nie nazwy pliku).

mogę to zrobić

 wc -l file.txt | awk '{print $1}'

Ale może jest lepszy sposób?


13
wc -l < file.txtwykonuje pracę precyzyjnie i zwięźle.
Jonathan Leffler


3
To jest pytanie, które sprawdziłem teraz dwukrotnie. Takie zachowanie wc jest nieintuicyjne i anty-paradygmatyczne dla zwykłej zwięzłości -nix. Ta zwięzłość istnieje z jakiegoś powodu, ponieważ dokładnie nie chcesz pracować nad wszystkimi rodzajami puszystej nadmiarowości. W końcu znam nazwę pliku, prawda? To, czego chcę, to liczba linii.
Peter - Przywróć Monikę

Odpowiedzi:


217

Spróbuj w ten sposób:

wc -l < file.txt

5
W systemie AIX ksh zawsze będzie miał spację poprzedzającą liczbę. Musimy użyć | awk '{print $ 1}' lub a cut, aby usunąć spacje. Innym sposobem przycinania byłoby objęcie echem.
rao

@rao jest poprawne, doda spację przed liczbą. Moje rozwiązanie rozwiązuje ten problem i jest prostsze niż awk czy cut.
Desi Cochrane

@rao W bash nie ma spacji. Skąd pochodzi przestrzeń w ksh? wc -lnie powinien emitować jednego i dlaczego ksh miałby poprzedzać standardowe wyjście programu spacją?
Peter - Przywróć Monikę

Chociaż jest to właściwe obejście (i dość łatwe, że wc nigdy nie zostało zmienione), prawdopodobnie jest wolniejsze i nieintuicyjne. Po pierwsze, spodziewałbym się czegoś takiego 4711 [stdin]jak wyjście.
Peter - Przywróć Monikę

Weź również pod uwagę parowanie z printf "%'d", które zajmuje się przestrzenią i ładnie drukuje duże liczby.
Leo

21
cat file.txt | wc -l

Zgodnie ze stroną podręcznika (dla wersji BSD nie mam wersji GNU do sprawdzenia):

Jeśli nie określono żadnych plików, używane jest standardowe wejście i nie jest wyświetlana żadna nazwa pliku. Monit będzie akceptował dane wejściowe do momentu otrzymania EOF lub [^ D] w większości środowisk.


3
Nie lubię kota - konkatenacja zabiera dużo czasu.
PoGibas

9
wc -l < file.txtma ten sam efekt.
pjmorse

@user: Przetestuj. Zdecydowanie najwolniejsza część będzie odczytywać plik z dysku.
sarnold

11
@ user1286528, a następnie użyj, wc -l < file.txtaby uniknąć niepotrzebnego używania cat. Chociaż jesteś absolutnie szalony, jeśli myślisz, że pochłania to zauważalny czas.
hobbs

12

Aby to zrobić bez wiodącej spacji, dlaczego nie:

wc -l < file.txt | bc

Otrzymuję błędy składniowe z tym (Ubuntu 14.04). Myślę, że wystąpił problem z nazwą pliku.
MERose,

W RHEL 6.7 powoduje to błędy: $ wc -l plik.csv | bc (standard_in) 1: błąd składni (standard_in) 1: niedozwolony znak: N (standard_in) 1: błąd składni (standard_in) 1: błąd składni
Rodrigo Hjort

3
Otrzymuję również błąd analizy, ale możesz połączyć to z inną odpowiedzią, wc -l < file.txtaby naprawić błąd analizy i usunąć spację:wc -l < file.txt | bc
jangosteve

11

Co powiesz na

wc -l file.txt | cut -d' ' -f1

tzn. potokuj wyjście wcdo cut(gdzie ograniczniki są spacjami i wybierz tylko pierwsze pole)


4
to nie jest lepsze niż wc -l file.txt | awk '{print $1}'próbował OP.
doubleDown

1
Szybciej niż wc -l < file.txtmetoda. Ale musi być używany | cut -d' ' -f2w BSD, o ile wcpolecenie zwraca początkową spację, na przykład: „34068289 plik.txt” zamiast „34068289 plik.txt”.
Sopalajo de Arrierez

@doubleDown, używanie awk jest jak używanie maszyny CNC do cięcia deski zamiast piły. Użyj piły do ​​piłowania.
Peter - Przywróć Monikę

5

Porównanie technik

Miałem podobny problem, próbując uzyskać liczbę znaków bez wiodących białych znaków dostarczonych przez wc, co doprowadziło mnie do tej strony. Po wypróbowaniu odpowiedzi tutaj, oto wyniki moich osobistych testów na komputerze Mac (BSD Bash). Ponownie dotyczy to liczby znaków; dla liczby linii, którą byś zrobił wc -l. echo -npomija koniec linii końcowej.

FOO="bar"
echo -n "$FOO" | wc -c                          # "       3"    (x)
echo -n "$FOO" | wc -c | bc                     # "3"           (√)
echo -n "$FOO" | wc -c | tr -d ' '              # "3"           (√)
echo -n "$FOO" | wc -c | awk '{print $1}'       # "3"           (√)
echo -n "$FOO" | wc -c | cut -d ' ' -f1         # "" for -f < 8 (x)
echo -n "$FOO" | wc -c | cut -d ' ' -f8         # "3"           (√)
echo -n "$FOO" | wc -c | perl -pe 's/^\s+//'    # "3"           (√)
echo -n "$FOO" | wc -c | grep -ch '^'           # "1"           (x)
echo $( printf '%s' "$FOO" | wc -c )            # "3"           (√)

Nie polegałbym na tej cut -f*metodzie w ogóle, ponieważ wymaga ona znajomości dokładnej liczby wiodących spacji, które może mieć dane wyjście. A ten grepsłuży do liczenia wierszy, ale nie znaków.

bcjest najbardziej zwięzły awki perlwydaje się nieco przesadzony, ale wszystkie powinny być stosunkowo szybkie i wystarczająco przenośne.

Zauważ również, że niektóre z nich można dostosować do przycinania otaczających białych znaków z ogólnych ciągów znaków (razem z echo `echo $FOO`inną fajną sztuczką).


1
echo $(printf '%s' "$FOO" | wc -c)jest jednym z rzadkich przypadków, gdy echopodmiana polecenia nie jest bezużyteczna.
tripleee

@tripleee Whoa ... w oparciu o Twój kod echo `echo $FOO`;działa również jak polecenie String.trim () na zmiennej! To niezwykle przydatne. Dodam również twoją linię do mojej odpowiedzi.
Beejor

Być może dla kontekstu zobacz także Kiedy zawijać cudzysłowy wokół zmiennej powłoki
tripleee,


4

Co powiesz na

grep -ch "^" file.txt

3
Miły. Bardzo oryginalne / kreatywne użycie, grepale po sprawdzeniu tego okazuje się (nie jest zaskakujące), że jest 2x do 6x wolniejsze niż prostsza / nieskomplikowana wcmetoda w moich testach.
arielf

3

Oczywiście istnieje wiele rozwiązań tego problemu. Oto jednak inny:

wc -l somefile | tr -d "[:alpha:][:blank:][:punct:]"

Ten wysyła tylko liczbę wierszy, ale charakter kroczący nowej linii ( \n) jest obecny, jeśli nie chce, że albo wymienić [:blank:]z [:space:].


Ma to problem, gdy nazwa pliku zawiera numer. Na przykład dla pliku test9zawierającego 1 linię wynik będzie wynosił 19.
Raphael Ahrens

1

Najlepszym sposobem byłoby przede wszystkim znalezienie wszystkich plików w katalogu, a następnie użycie AWK NR (Zmienna liczby rekordów)

poniżej znajduje się polecenie:

find <directory path>  -type f | awk  'END{print NR}'

przykład: - find /tmp/ -type f | awk 'END{print NR}'


0

Działa to w przypadku mnie, używając normalnego wc -li sedusuwania wszelkich znaków, które nie są liczbą.

wc -l big_file.log | sed -E "s/([a-z\-\_\.]|[[:space:]]*)//g"

# 9249133
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.