Jak mogę użyć licznika słów ( wc
) i potoków, aby policzyć, ile plików lub katalogów znajduje się w /usr/bin
katalogu?
Jak mogę użyć licznika słów ( wc
) i potoków, aby policzyć, ile plików lub katalogów znajduje się w /usr/bin
katalogu?
Odpowiedzi:
Jednym z podejść byłoby skorzystanie z, ls
aby dać nam listę plików, ale chcemy, aby ta lista wyświetlała tylko 1 plik lub katalog w wierszu. -1
Przełącznik zrobi to za nas.
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
Utwórz powyższe przykładowe dane w pustym katalogu.
$ mkdir dir{1..3}
$ touch file{A..C}
Sprawdź to:
$ ls
dir1 dir2 dir3 fileA fileB fileC
Teraz do zliczenia można użyć wc -l
do zliczenia liczby wierszy odpowiadających plikowi lub katalogowi w danych ls -1
wyjściowych.
$ ls -1 | wc -l
6
(zauważ jednak, że nie zawiera ukrytych plików)
Aby policzyć pliki lub katalogi, musisz nieco zmienić taktykę. W tym przypadku skorzystałbym, ls -l
ponieważ pokazuje, co to jest katalog, a co plik.
$ ls -l
total 12
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
Następnie możemy użyć grep
do odfiltrowania katalogów lub katalogów innych niż katalogi:
# directories
$ ls -l | grep "^d"
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
# regular files
$ ls -l | grep "^-"
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
Teraz użyj wc -l
ponownie, aby policzyć powyższe:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
Chociaż można uniknąć wc
całkowicie, a stosowanie grep
jest -c
opcja:
$ ls -l | grep -c '^d'
(znowu, ukryte pliki nie są uwzględnione. Pamiętaj, że katalogi i zwykłe są dwoma typami plików. Istnieje wiele innych, takich jak nazwane potoki, dowiązania symboliczne, urządzenia, gniazda ...).
Jeśli potrzebujesz rekursywnie znaleźć pliki i katalogi /usr/bin
, prawdopodobnie zechcesz całkowicie zmienić taktykę i skorzystać z innego narzędzia o nazwie find
.
$ find /usr/bin | wc -l
4632
(chociaż powyżej /usr/bin
siebie jest wliczone w liczenie)
Tych samych technik, których użyłem powyżej, można użyć ls
do zrobienia czegoś podobnego, ale ls
ogólnie nie jest to dobre narzędzie do analizy wyników. find
z drugiej strony został stworzony do tego i oferuje przełączniki do wyszukiwania plików lub katalogów.
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(zauważ, że tym razem find
zawiera ukryte pliki (oprócz .
i ..
)).
Nigdy nie dowiedziałem się, dlaczego znak nowej linii jest znakiem legalnym, którego można używać podczas tworzenia nazw plików lub nazw katalogów. Tak więc metody omówione powyżej wykorzystują wc
i ls
nie byłyby z nimi sprzeczne, więc używaj ich z myślą o tym.
Utwórz katalog i nazwę pliku z nowymi liniami.
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls
pokazuje je poprawnie:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
Ale wc
liczy katalogi i pliki zawierające znaki nowej linii jako 2 elementy, a nie jeden.
$ ls -1 | wc -l
10
Jedną z metod obejścia tego problemu , jeśli używa się implementacji GNU, find
jest wykorzystanie find
możliwości wydrukowania czegoś innego w miejsce każdego znalezionego pliku, a następnie policzenie go zamiast tego.
$ find . -printf . | wc -c
9
Tutaj jesteśmy odkrycie wszystko w bieżącym katalogu (z wyjątkiem ..
), a drukuje kropki ( .
) dla każdego, a następnie liczenie kropek za pomocą wc
„s zdolność count bajtów zamiast linii wc -c
.
/usr/bin
będą dobrze sformatowane (i nie będą zawierały spacji, więc technicznie możesz nawet po prostu echo * | wc -w
), warto zauważyć, że wszystkie zepsują się na nazwach plików zawierających nowe linie.
ls -l
lub ls -1
złamie b / c liczymy linie, a nie słowa! find
Może pęknąć, ale znowu liczymy linie nie słowa.
touch $'foo\nbar'
w pustym katalogu, po którym następuje jedno z twoich poleceń (powiedzmy ls -1 | wc -l
) zgłasza dwa pliki, a nie jeden - ponieważ ten plik ma dwie linie wc
. Chyba że ls
zastąpi nowy wiersz inną postacią (nie sądzę, że tak, ale znowu nie jestem teraz w stanie przetestować).
wc -c
jest problem z liczeniem okresów?
Jeśli chcesz uzyskać podział liczby każdego typu plików rekurencyjnie w jakimś katalogu, z GNU find
, możesz zrobić:
find /some/dir/. ! -name . -printf '%y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
W /usr/bin
moim systemie daje to:
3727 regular files
710 symbolic links
On /dev
:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
W przypadku dowiązań symbolicznych, jeśli wolisz je policzyć jako typ pliku, na który wskazują symbolic links
, możesz zmienić to na:
find /some/dir/. ! -name . -printf '%Y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/N/broken symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
Co teraz daje moje /usr/bin
:
1 directories
4434 regular files
2 broken symbolic links
(zepsute dowiązanie symboliczne to dowiązanie symboliczne do pliku, dla którego find
nie można określić typu, ponieważ plik nie istnieje lub znajduje się w katalogu, do którego nie masz dostępu, lub istnieje pętla w rozdzielczości ścieżki do pliku W moim przypadku te 2, w których dowiązania symboliczne do plików, które już zniknęły).
Żaden z nich się nie liczy .
i ..
. Jeśli chcesz je uwzględnić (dlaczego?), Nie ma innego wyjścia find
niż założenie, że są one dostępne dla każdego katalogu i licz je systematycznie:
find /some/dir/. -printf '%y\n' \( -name . -printf 'd\n' -o \
-type d -printf 'd\nd\n' \) | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
Co następnie daje moje /usr/bin
:
2 directories
3727 regular files
710 symbolic links
Jeśli nie masz dostępu do GNU find
, możesz przepisać pierwszy jako:
find /some/dir/. ! -name . \( \
-type f -exec printf '%.0sregular files\n' {} + -o \
-type d -exec printf '%.0sdirectories\n' {} + -o \
-type l -exec printf '%.0ssymbolic links\n' {} + -o \
-type s -exec printf '%.0sUnix domain sockets\n' {} + -o \
-type b -exec printf '%.0sblock devices\n' {} + -o \
-type c -exec printf '%.0scharacter devices\n' {} + -o \
-type p -exec printf '%.0sFIFOs\n' {} + -o \
-exec printf '%.0sothers\n' {} + \) | sort | uniq -c
Mówiąc ściśle, nie liczymy plików, ale wpisy katalogu . Jak /usr/bin
zwykle katalog zawiera kilka pozycji wskazujących na ten sam plik. Na przykład tutaj mam:
$ ls -lid /usr/bin/{nvi,nview,nex}
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nex
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nvi
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nview
Są to 3 wpisy katalogu (inaczej nazwy plików lub twarde łącza) do tego samego pliku (ten z i-węzłem 672252. Aby policzyć pliki zamiast pozycji katalogu i GNU find
i GNU uniq
(ignorowanie .
i ..
pliki, które i tak są twardymi linkami do innych katalogów):
find /some/dir/. ! -name . -printf '%y\t%D:%i\n' |
sort -u |
cut -f1 |
uniq -c |
sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/d/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
W moim /usr/bin
przypadku daje to:
3711 regular files
710 symbolic links
Nie powiedziałeś, czy chcesz rekursywnie cały plik w / usr / bin, czy tylko poniżej pierwszego poziomu. Poza tym, jak zdobędziesz wyliczane słowa? Zwykłym sposobem na sprawdzenie tego jest uruchomienie find w wc. W ten sposób: znajdź / usr / bin | wc -l Znajdź wyświetli wszystko, katalogi i pliki. Wc -l policzy wszystkie linie w wynikach wyszukiwania. Czy to zadanie klasowe? W porządku, jeśli tak, ale zastanawiałem się, dlaczego potrzebowałeś tych informacji, aby móc dokładniej dostosować odpowiedź. Daj mi znać, jeśli potrzebujesz więcej. Costa
W skrócie, bez zewnętrznych narzędzi.
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
W skrócie, bez zewnętrznych narzędzi i rekurencji.
shopt -s globstar; shopt -s dotglob
for dir in **/*/; do
unset d f
for files in "$dir"*; do
[[ -f $files ]] && ((++f))
[[ -d $files ]] && ((++d))
done;
printf '%s\n' "$dir - files: ${f:-0} - directories: ${d:-0}"
done
.
ani ..
wpisów. Możesz rozróżnić plik od zwykłego pliku.