Jak uzyskać liczbę plików w katalogu przy użyciu wiersza polecenia?

193

Mam katalog z dużą liczbą plików. Nie widzę lsprzełącznika do podania liczby. Czy jest jakaś magia z wiersza poleceń, aby uzyskać liczbę plików?

Blake
źródło
tree . | taillub tree -a . | taildołączanie ukrytych plików / katalogów, treejest rekurencyjne, jeśli tego właśnie chcesz.
CodyChan,

Odpowiedzi:

239

Korzystanie z szerokiej definicji „pliku”

ls | wc -l

(zwróć uwagę, że nie uwzględnia ukrytych plików i zakłada, że ​​nazwy plików nie zawierają znaków nowej linii).

Aby dołączyć ukryte pliki (oprócz .i ..) i uniknąć problemów ze znakami nowej linii, kanoniczny sposób to:

find . ! -name . -prune -print | grep -c /

Lub rekurencyjnie:

find .//. ! -name . -print | grep -c //
James Roth
źródło
23
wcto program do „liczenia słów”. -lPrzełącznik powoduje je policzyć wiersze. W tym przypadku zlicza linie na wyjściu z ls. W ten sposób zawsze uczono mnie, jak uzyskać liczbę plików dla danego katalogu.
Sandy
20
proszę dodać uwagę, że lstak jest, ls -1jeśli wyjście jest potokiem.
lesmana
6
który nie zawiera wszystkiego w katalogu - brakuje Ci plików kropek i zbierasz też kilka dodatkowych wierszy. Pusty katalog nadal zwróci 1 linię. A jeśli zadzwonisz ls -la, otrzymasz trzy linie do książki telefonicznej. Chcesz ls -lA | wc -lpominąć wpisy .i ... Nadal będziesz jednak traktowany osobno.
1
Pusty katalog zwraca mi 0
James Roth
2
Poprawione podejście, które nie liczyłoby podwójnie plików z nową linią w nazwie, byłoby następujące: ls -q | wc -l- chociaż zauważ, że ukryte pliki nadal nie będą liczone przez to podejście i że katalogi zostaną policzone.
godlygeek
30

W przypadku wąskiej definicji pliku:

 find . -maxdepth 1 -type f | wc -l
Maciej Piechotka
źródło
I oczywiście można pominąć -maxdepth 1rekurencyjne zliczanie plików (lub dostosować je do żądanej maksymalnej głębokości wyszukiwania).
user7089,
1
Jeśli masz plik, którego nazwa zawiera nowy wiersz, to podejście nieprawidłowo policzy go dwukrotnie.
godlygeek
7
Poprawione podejście, które nie find -maxdepth 1 -type f -printf "\n" | wc -l
liczyłoby
+1 Zezwalaj na ukryte pliki i ignoruje katalogi
Michael Durrant
13
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS: Uwaga ls - <numer-one> | wc - <letter-l>

nicomen
źródło
10
Większość wersji lszrobić -1automatycznie, gdy wyjście jest w rurze.
Dennis Williamson
3
@Dennis to ciekawe Nie wiedziałem, że aplikacja może powiedzieć, że jej wyjście przechodzi do potoku.
ksenoterrakid
1
Dodałem + + do tej wersji, ponieważ jest bardziej jednoznaczna. Chociaż tak, ls używa -1, jeśli jest potokowany (spróbuj: ls | cat), uważam, że składnia -1 jest bardziej wyraźna.
Gabe.
3
@xenoterracide: In Bash:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
Dennis Williamson
2
W moich testach było znacznie szybsze także podanie opcji -f, aby uniknąć sortowania nazw plików przez ls. Niestety nadal otrzymujesz złą odpowiedź, jeśli twoje nazwy plików zawierają nowe linie.
Samuel Edwin Ward
10

Prawdopodobnie najbardziej kompletna odpowiedź przy użyciu ls/ wcpair jest

ls -Aq | wc -l

jeśli chcesz policzyć pliki kropkowe, i

ls -q | wc -l

Inaczej.

  • -Ato zliczać pliki kropkowe, ale pomijaj .i ...
  • -qmake lszamień znaki niebędące znakami graficznymi, w szczególności znak nowej linii ?, tworząc wynik 1 linię dla każdego pliku

Aby uzyskać wyjście jednowierszowe z lsterminala (tj. Bez podłączania do niego wc), -1należy dodać opcję.

(zachowanie lstestowane z Coreutils 8.23)

Frax
źródło
2
Jak powiedziałeś, -1nie jest potrzebne. Jeśli chodzi o „rozsądnie obsługuje nowe wiersze w nazwach plików z wyjściem konsoli” , dzieje się tak z powodu -qprzełącznika (którego należy użyć zamiast, -bponieważ jest przenośny), który „Wymusza zapisanie każdego wystąpienia niedrukowalnych znaków nazw plików i znaków <tab> jako znak <znak zapytania> („?”). Implementacje mogą domyślnie udostępniać tę opcję, jeśli dane wyjściowe dotyczą urządzenia końcowego. ” Na przykład, ls -Aq | wc -laby policzyć wszystkie pliki / katalogi lub ls -qp | grep -c /policzyć tylko
katalogi
Dzięki za wkład. Zmieniono -bna -q.
Frax
7

Jeśli wiesz, że bieżący katalog zawiera co najmniej jeden nie ukryty plik:

set -- *; echo "$#"

Można to oczywiście uogólnić na dowolny glob.

W skrypcie ma to czasami niefortunny efekt uboczny nadpisania parametrów pozycyjnych. Można obejść ten problem, używając podpowłoki lub funkcji (wersja Bourne / POSIX), takiej jak:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

Alternatywnym rozwiązaniem jest $(ls -d -- * | wc -l). Jeśli glob jest *, polecenie można skrócić $(ls | wc -l). Analiza wyniku lszawsze powoduje, że jestem niespokojny, ale tutaj powinien on działać tak długo, jak długo twoje nazwy plików nie zawierają znaków nowej linii, lub twoje znaki lsucieczki. I $(ls -d -- * 2>/dev/null | wc -l)ma tę zaletę, że z wdziękiem obsługuje przypadek niepasującego globu (tzn. Zwraca 0 w tym przypadku, podczas gdy set *metoda wymaga skomplikowanego testowania, czy glob może być pusty).

Jeśli nazwy plików mogą zawierać znaki nowego wiersza, można zastosować alternatywę $(ls -d ./* | grep -c /).

Każde z tych rozwiązań, które opiera się na przekazaniu rozszerzenia globu, lsmoże zawieść z powodu zbyt długiego błędu listy argumentów, jeśli istnieje wiele pasujących plików.

Gilles
źródło
1
Czy naprawdę chcesz utworzyć 13923 parametry pozycyjne? I powinieneś zmienić lokalną zmienną locallub ją wyeliminować: eval $1=$#lub po prostu użyć echo $#i zrobić number_of_files=$(count_words *).
Dennis Williamson
1
@Dennis: częścią tego było uniknięcie rozwidlenia. Chyba nie jest to problem XXI wieku. Ok, przyznaję, że nie dbam już o powłoki inne niż POSIX, więc mogłem uniknąć zmiennej tymczasowej.
Gilles
Dlaczego odjęłeś jeden z nich $#(nie zrobiłeś tego przed edycją)?
Dennis Williamson
@Dennis: Nadal unikam rozwidlenia (cóż, robi to różnicę na komputerach z wolnym procesorem, takim jak routery) i przekazuję nazwę zmiennej jako $1. Chcę więc policzyć liczbę parametrów, które nie są pierwszym parametrem. (Nie mogę użyć, shiftponieważ muszę zachować nazwę zmiennej w pobliżu.) (Umm, teraz, gdybyś zapytał o pierwszą linię ...)
Gilles
@Dennis: przyjdź i zastanów się, mogę użyć, shiftjeśli dobrze to zaplanuję .
Gilles
7

Uznałem, że jest du --inodesprzydatny, ale nie jestem pewien, która wersja dutego wymaga. Powinno być znacznie szybsze niż podejście alternatywne z wykorzystaniem findi wc.

W systemie Ubuntu 17.10 działa:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

Połącz z, | sort -nraby posortować malejąco według liczby zawierających i-węzłów.

krlmlr
źródło
5

Podczas korzystania z pary ls / wc, jeśli dodajemy -U, będzie to znacznie szybsze (nie sortuj).

ls -AqU | wc -l
Jbnair
źródło
1
-Ujest jednak specyficzny dla GNU.
Stéphane Chazelas
4

Po zainstalowaniu polecenia drzewa wpisz:

tree

Jeśli chcesz też ukrytych plików:

tree -a

Jeśli używasz systemu Debian / Mint / Ubuntu Linux, wpisz następujące polecenie, aby zainstalować polecenie drzewa:

sudo apt-get install tree

Opcja -L służy do określania maksymalnego poziomu wyświetlania drzewa katalogów. Polecenie tree nie tylko liczy liczbę plików, ale także liczbę katalogów, biorąc pod uwagę tyle poziomów drzewa katalogów, ile chcesz.

lew
źródło
Kiedy wpisuję drzewo, dostaję rodzaj drzewa wyjściowego na ekran katalogu, w którym jestem, ale nie widzę, gdzie jest wyświetlana liczba plików.
charlesdarwin,
2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1sprawi, że będzie nierekurencyjny, finddomyślnie będzie rekurencyjny
  • -type f będzie zawierać tylko pliki
  • -printf .to uroczy akcent. wypisuje kropkę dla każdego pliku zamiast nazwy pliku, a teraz jest w stanie obsłużyć dowolną nazwę pliku, a także zapisuje dane; musimy tylko policzyć kropki :)
  • | wc -c liczy znaki
aude
źródło
1

Bez rury, bez kopii struny, bez widelca, po prostu zwykłe uderzenie jednej wkładki

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount
DaboD
źródło
1
Podaje wartość 1, jeśli w katalogu nie ma żadnych plików. Nie liczy plików, liczy pliki i katalogi.
steve
1

Oto kolejna technika podobna do tej, którą napisał Gilles :

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

co tworzy tablicę z 13,923 elementami (jeśli tyle jest plików).

Dennis Williamson
źródło
Jaki jest sens tej ctablicy? word_count() { echo "$#"; }powinno wystarczyć. Celem rozwiązania @Gilles jest przechowywanie liczby w zwracanej zmiennej, aby uniknąć konieczności zastępowania poleceń (co obejmuje rozwidlenie i potok w powłokach innych niż ksh93).
Stéphane Chazelas
1
find . -type f -maxdepth 1 |  wc -l 

Może to zawierać tylko pliki w bieżącym katalogu.

pappu
źródło
find . -type fznajdzie pliki w bieżącym katalogu, a także rekurencyjnie w podkatalogach.
dhag
0

Spróbuj tego, mam nadzieję, że ta odpowiedź ci pomoże

echo $((`ls -l | wc -l` -1 ))
Tygrys
źródło
0

Możesz to sprawdzić za pomocą:

ls -l | grep -v ^l | wc -l
AMIC MING
źródło
0

Poprawianie niektórych odpowiedzi udzielonych wcześniej, ale tym razem wyraźnie.

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

Warto zauważyć użycie niektórych ulubionych poleceń, takich jak taili cut. Pamiętaj też, że drzewo nie jest domyślnie dostępne. Polecenie powyżej najpierw przechwytuje informacje o katalogu na poziomie 1, a następnie pobiera ostatni wiersz, w tail -n 1którym jest nasz cel, i kończy się cutna wzięciu trzeciego słowa.

Na przykład lokalizowanie w /:

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

Co powiesz na pytanie o liczbę katalogów?

jonaprieto
źródło
0

W systemie Linux, aby polecenie było bardzo niezawodne i obsługiwało pliki, które mogą mieć w nazwie znaki nowej linii, użyj tego:

find -maxdepth 1 -type f -print0 | tr -cd '\0' | wc -c

To nas ratuje przed próbą przetworzenia ls.


Związane z:

codeforester
źródło
-2

Użyj treepolecenia, po prostu:

tree
użytkownik115186
źródło