12Widać nie jest to liczba plików, ale liczba bloków dyskowych spożywane.
Od info coreutils 'ls invocation':
For each directory that is listed, preface the files with a line
`total BLOCKS', where BLOCKS is the total disk allocation for all
files in that directory. The block size currently defaults to 1024
bytes, but this can be overridden (*note Block size::). The
BLOCKS computed counts each hard link separately; this is arguably
a deficiency.
Całkowita idzie od 12celu 20, gdy używasz ls -lazamiast ls -lbo liczą dwa dodatkowe katalogi: .a ... Używasz czterech bloków dysku dla każdego (pustego) katalogu, więc twoja suma wynosi od 3 × 4 do 5 × 4. (Najprawdopodobniej używasz jednego bloku dysku o długości 4096 bajtów dla każdego katalogu; jak infowskazuje strona, narzędzie nie sprawdza formatu dysku, ale przyjmuje rozmiar bloku, o 1024ile nie podano inaczej.)
Jeśli chcesz po prostu uzyskać liczbę plików, możesz spróbować czegoś takiego
ls | wc -lzakoń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
Flimm
20
„jeśli w nazwach plików znajduje się nowa linia” ... wzdryga się
Petah,
8
Jak man lspowiedzą ci, możesz unikać znaków kontrolnych za pomocą -b(ucieka je) lub -q(pomija je). Więc do zliczania, ls -1q | wc -ljest bezpieczny i dokładny do pokazywania nie ukrytych plików. ls -1qA | wc -lliczyć ukryte pliki (ale nie .i ..). Używam -1zamiast, -lponieważ powinno to być szybsze.
Oli
18
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 lsjest 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 -lpowiedzieliś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
findPoleceń, 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 1aby zapobiec rekurencyjnemu schodzeniu do podkatalogów)
setpolecenie 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/shograniczenia 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ć
Podobna findmetoda jak w przypadku metody wci globstar może być użyta statdo 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 forpę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
W bash inną opcją byłoby użycie tablicy np. items=( dir/* ); echo ${#items[@]}(Dodanie w shopt -s dotglobcelu włączenia ukrytych plików).
steeldriver,
1
Drukowanie numerów i-węzłów ułatwia filtrowanie linków w razie potrzeby za pomocą find | sort -u | wc -l.
Peter Cordes,
@steeldriver: Myślę, że metoda bash-tablic raczej nie będzie szybsza. Jeśli chcesz, aby był rekurencyjny, musisz użyć items=( dir/** )(z shopt -s globstar), ale bash nie korzysta z dodatkowych metadanych z readdir, więc statystyki każdego wpisu katalogu, aby zobaczyć, czy jest to sam katalog. Wiele systemów plików przechowuje typ pliku we wpisie katalogu, więc readdir może go zwrócić bez dostępu do i-węzłów. (np. najnowszy nie-domyślny XFS ma to i myślę, że ext4 ma to dłużej.) Jeśli straceznajdziesz, zobaczysz o wiele mniej statwywołań systemowych niż strash bash.
Peter Cordes,
2
Dlaczego nie po prostu użyć print(len(os.listdir('.')))? Mniej znaków do wpisania, a także unika dostępu do podwójnie podkreślonych atrybutów.
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
man ls
powiedzą ci, możesz unikać znaków kontrolnych za pomocą-b
(ucieka je) lub-q
(pomija je). Więc do zliczania,ls -1q | wc -l
jest bezpieczny i dokładny do pokazywania nie ukrytych plików.ls -1qA | wc -l
liczyć ukryte pliki (ale nie.
i..
). Używam-1
zamiast,-l
ponieważ powinno to być szybsze.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ściuls
(które ma), ale w rzeczywistości w katalogu są tylko 4 pliki.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)Metoda nr 2: globstar
Prosty, szybki i najczęściej przenośny sposób:
set
polecenie służy do ustawiania parametrów pozycyjnych powłoki ($<INTEGER>
zmienne, jak wecho $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ćzgodnie z propozycją steeldriver w komentarzach .
Podobna
find
metoda jak w przypadku metodywc
i globstar może być użytastat
do zliczania liczb i-węzłów w linii: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
)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).Zobacz też
źródło
items=( dir/* ); echo ${#items[@]}
(Dodanie wshopt -s dotglob
celu włączenia ukrytych plików).find | sort -u | wc -l
.items=( dir/** )
(zshopt -s globstar
), ale bash nie korzysta z dodatkowych metadanych z readdir, więc statystyki każdego wpisu katalogu, aby zobaczyć, czy jest to sam katalog. Wiele systemów plików przechowuje typ pliku we wpisie katalogu, więc readdir może go zwrócić bez dostępu do i-węzłów. (np. najnowszy nie-domyślny XFS ma to i myślę, że ext4 ma to dłużej.) Jeślistrace
znajdziesz, zobaczysz o wiele mniejstat
wywołań systemowych niż strash bash.print(len(os.listdir('.')))
? Mniej znaków do wpisania, a także unika dostępu do podwójnie podkreślonych atrybutów.