Podczas liczenia linii za pomocą wc nie drukuj błędu, ilekroć jest katalog

12

Chcę policzyć całkowitą liczbę wierszy we wszystkich /etcplikach, ale nie w plikach w podkatalogach, więc wpisałem: wc -l /etc/* | tail -1a dane wyjściowe są następujące:

xxxx is a directory 
yyyy is a directory
total 1752

Moje pytanie brzmi: w jaki sposób mogę pozbyć się (usunąć) tych komentarzy i czy istnieje lepszy sposób na obliczenie tego typu?

Hamza
źródło
1
Myślę, że użycie find nie jest w 100% wrightem, ponieważ w / etc są nie tylko zwykłe pliki f, ale także linki l. więc ta wersja jest znacznie lepsza: $ sudo wc -l / etc / * 2> / dev / null | tail -1
Hamza

Odpowiedzi:

14

Możesz wysyłać komunikaty o błędach do / dev / null

$ wc -l /etc/* 2>/dev/null | tail -1

Dzięki temu poleceniu widzisz tylko liczbę linii w plikach, które można odczytać na całym świecie. Aby zobaczyć liczbę wierszy wszystkich plików, musisz podwyższyć komendę sudo.

$ sudo wc -l /etc/* 2>/dev/null | tail -1
LD James
źródło
8

Izoluj pliki i uruchom na nich wc

Co wc -l /etc/*robi jest, że *wzrośnie do wszystkich elementów wewnątrz /etc/katalogu. Dlatego celem jest izolowanie plików i wykonywanie wcna nich. Można to zrobić na kilka sposobów.

dla pętli z testem

testPoleceń, lub częściej w skrócie [można wykorzystać do znalezienia, czy dany element jest zwykłym plikiem tak:

[ -f "$FILE" ]

W ten sposób możemy iterować wszystkie elementy /etc/i uruchamiać wcje wtedy i tylko wtedy, gdy powyższe polecenie zwróci wartość true. Tak jak:

for i in /etc/*; do [ -f "$i" ] && wc -l "$i" ; done             

odnaleźć

Możemy również skorzystać findz -maxdepth, -typei -execflagi

find /etc/ -maxdepth 1 \( -type f -o -type l \) -exec wc -l {} +

  • -maxdepthinformuje, jak głęboko w strukturze katalogów iść; wartość 1 oznacza tylko pliki w wybranym przez nas katalogu.
  • -type f każe mu szukać zwykłych plików, LUB (reprezentowanych przez -oflagę) dla linków sybolicznych (reprezentowanych przez type l). Wszystko to dobroć jest zamknięty w nawiasach ()uciekły z \tak który interpretuje je jako powłoki części do findpolecenia, a nie coś innego.
  • -exec COMMAND {} +struktura tutaj uruchamia dowolne polecenie, które mu dajemy, +wskazując, że weźmie wszystkie znalezione pliki i umieści je jako argumenty linii poleceń w poleceniu.

Aby można było łącznie wytwarzają wyjściowy do rury tailpodobnie jak

$ find /etc/ -maxdepth 1 \( -type f -o -type l \) -exec wc -l {} + | tail -n 1           
[sudo] password for xieerqi: 
 11196  total

Dygresja

Łatwiej jest go używać wc -l /etc/* 2>/dev/null | tail -1, jak w odpowiedzi LD Jamesa, jednak findpowinien być częścią nawyku postępowania z plikami, aby uniknąć przetwarzania trudnych nazw plików. Aby uzyskać więcej informacji na ten temat, przeczytaj esej Jak poprawnie postępować z nazwami plików

Sergiy Kolodyazhnyy
źródło
5

find robi to łatwo:

sudo wc -l $(find /etc/ -maxdepth 1 -type f -iname '*')

Wynik:

...
828 /etc/mime.types
25 /etc/ts.conf
66 /etc/inputrc
 0 /etc/subgid-
8169 total

ALE jeśli chcesz tylko liczbę jako wynik i nic więcej:

sudo wc -l $(find /etc/ -maxdepth 1 -type f -iname '*') | grep total | awk '{print $1}'

EDYCJA : newlinesbłąd kos powiedział, że przeważa. Tylko użycie -execgo naprawia. Ponadto /etcnie zawiera takich plików.

Wynik:

8169

Jak wskazuje kos , powyższe polecenie można zredukować do:

sudo wc -l $(find /etc/ -maxdepth 1 -type f -iname '*') | awk 'END {print $1}'

EDYCJA : newlinesbłąd kos powiedział, że przeważa. Tylko użycie -execgo naprawia. Ponadto /etcnie zawiera takich plików.

Wynik:

8169
Raphael
źródło
4
Jaki jest cel -iname '*'? finddomyślnie nie pasuje do wszystkiego?
steeldriver
@steeldriver - Bez mnie to nie działało '*'.
Raphael
2

Użycie z-shell ( zsh), królowej powłok , zamiast bash.

sudo wc -l /etc/*(.) | tail -1
AB
źródło