Jak mogę użyć licznika słów ( wc) i potoków, aby policzyć, ile plików lub katalogów znajduje się w /usr/binkatalogu?
Jak mogę użyć licznika słów ( wc) i potoków, aby policzyć, ile plików lub katalogów znajduje się w /usr/binkatalogu?
Odpowiedzi:
Jednym z podejść byłoby skorzystanie z, lsaby dać nam listę plików, ale chcemy, aby ta lista wyświetlała tylko 1 plik lub katalog w wierszu. -1Przełą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 -ldo zliczenia liczby wierszy odpowiadających plikowi lub katalogowi w danych ls -1wyjś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 -lponieważ 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ć grepdo 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 -lponownie, aby policzyć powyższe:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
Chociaż można uniknąć wccałkowicie, a stosowanie grepjest -copcja:
$ 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/binsiebie jest wliczone w liczenie)
Tych samych technik, których użyłem powyżej, można użyć lsdo zrobienia czegoś podobnego, ale lsogólnie nie jest to dobre narzędzie do analizy wyników. findz 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 findzawiera 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ą wci lsnie 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 wcliczy 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, findjest wykorzystanie findmoż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/binbę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 -llub ls -1złamie b / c liczymy linie, a nie słowa! findMoż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 lszastąpi nowy wiersz inną postacią (nie sądzę, że tak, ale znowu nie jestem teraz w stanie przetestować).
wc -cjest 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/binmoim 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 findnie 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 findniż 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/binzwykle 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 findi 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/binprzypadku 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.