użytkownik4556274 już odpowiedział na pytanie dlaczego . Moja odpowiedź służy jedynie do dostarczenia dodatkowych informacji na temat prawidłowego liczenia plików.
W społeczności Uniksa ogólny konsensus jest taki, że analiza wyniku ls
jest bardzo, bardzo złym pomysłem , ponieważ nazwy plików mogą zawierać znaki kontrolne lub znaki ukryte. Na przykład, ze względu na znak nowej linii w nazwie pliku, ls | wc -l
powiedzieliśmy, że jest 5 wierszy na wyjściu ls
(które ma), ale w rzeczywistości w katalogu są tylko 4 pliki.
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
Metoda nr 1: Znajdź narzędzie
find
Poleceń, który jest zwykle używany do pracy około analizowania nazw plików, może pomóc nam tutaj przez wydrukowanie numeru węzła . Czy to katalog, czy plik, ma tylko jeden unikalny numer i-węzła. Tak więc, używając -printf "%i\n"
i wykluczając .
za pośrednictwem -not -name "."
, możemy mieć dokładną liczbę plików. (Zwróć uwagę na użycie, -maxdepth 1
aby zapobiec rekurencyjnemu schodzeniu do podkatalogów)
$> find -maxdepth 1 -not -name "." -print
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find -maxdepth 1 -not -name "." -printf "%i\n" | wc -l
4
Metoda nr 2: globstar
Prosty, szybki i najczęściej przenośny sposób:
$ set -- *
$ echo $#
228
set
polecenie służy do ustawiania parametrów pozycyjnych powłoki ( $<INTEGER>
zmienne, jak w echo $1
). Jest to często używane do obejścia /bin/sh
ograniczenia brakujących tablic. Wersję, która wykonuje dodatkowe kontrole, można znaleźć w odpowiedzi Gille na Unix i Linux.
W powłokach obsługujących tablice, takich jak bash
, możemy użyć
items=( dir/* )
echo ${#items[@]}
zgodnie z propozycją steeldriver w komentarzach .
Podobna find
metoda jak w przypadku metody wc
i globstar może być użyta stat
do zliczania liczb i-węzłów w linii:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
Alternatywnym podejściem jest użycie symbolu wieloznacznego w for
pętli. (Uwaga: ten test używa innego katalogu do sprawdzenia, czy to podejście schodzi do podkatalogów, a tak nie jest - 16 to zweryfikowana liczba elementów w moim ~/bin
)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
Metoda nr 3: inne języki / tłumacze
Python może również radzić sobie z problematycznymi nazwami plików, drukując długość listy podanej przez moją os.listdir()
funkcję (która nie jest rekurencyjna i wyświetla tylko pozycje w katalogu podanym jako argument).
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4
Zobacz też
ls | wc -l
zakończy się niepowodzeniem, jeśli w nazwie pliku znajdują się pliki z nowym wierszem. Jest to bardziej odporne:find . -mindepth 1 -maxdepth 1 -printf . | wc -c