Как я могу использовать счетчик слов ( wc) и трубопровод, чтобы подсчитать, сколько файлов или каталогов в /usr/binкаталоге?
Как я могу использовать счетчик слов ( wc) и трубопровод, чтобы подсчитать, сколько файлов или каталогов в /usr/binкаталоге?
Ответы:
Один из подходов состоит в том, чтобы использовать lsдля предоставления нам список файлов, но мы хотим, чтобы этот список гарантированно отображал только 1 файл или каталог на строку. -1Выключатель будет делать это для нас.
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
Создайте приведенные выше примеры данных в пустом каталоге.
$ mkdir dir{1..3}
$ touch file{A..C}
Проверь это:
$ ls
dir1 dir2 dir3 fileA fileB fileC
Теперь для подсчета вы можете использовать wc -lдля подсчета количества строк, которые соответствуют файлу или каталогу в ls -1выводе.
$ ls -1 | wc -l
6
(обратите внимание, однако, что он не включает скрытые файлы)
Для подсчета файлов или каталогов вам нужно немного изменить свою тактику. В этом случае я бы использовал, ls -lпоскольку он показывает, что такое каталог и что такое файл.
$ 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
Затем мы можем использовать grepдля фильтрации каталогов или не-каталогов следующим образом:
# 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
Теперь просто используйте еще wc -lраз для подсчета выше:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
Хотя, вы можете избежать в wcцелом, и использования grep«s -cварианта:
$ ls -l | grep -c '^d'
(опять же, скрытые файлы не включены. Обратите внимание, что каталоги и обычные файлы - это два типа файлов. Есть много других, таких как именованные каналы, символические ссылки, устройства, сокеты ...).
Если вам нужно рекурсивно находить файлы и каталоги, /usr/binто вы, вероятно, захотите полностью изменить тактику и использовать другой инструмент под названием find.
$ find /usr/bin | wc -l
4632
(хотя над /usr/binсобой входит в счет)
Те же методы, которые я использовал выше, могут быть использованы lsдля lsсоздания чего-то похожего, но, как правило, не являются хорошим инструментом для анализа выходных данных. findс другой стороны, был создан для этого и предлагает переключатели для поиска файлов или каталогов.
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(обратите внимание, что в этот раз findвключаются скрытые файлы (кроме .и ..)).
Я никогда не понимал, почему символ новой строки является допустимым символом, который следует использовать при создании имен файлов или каталогов. Таким образом, методы, рассмотренные выше, используют wcи lsне будут противоречить этим, поэтому используйте их с учетом этого.
Создайте каталог и имя файла с символами новой строки.
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls показывает их правильно:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
Но wcсчитает каталоги и файлы, которые содержат переводы строк, как 2 элемента, а не как один.
$ ls -1 | wc -l
10
Один из способов обойти это, если используется реализация GNU find- это использовать findвозможность печатать что-то еще вместо каждого файла, который он находит, а затем подсчитывать их.
$ find . -printf . | wc -c
9
Здесь мы находим все в текущем каталоге ( за исключением ..), и печать точка ( .) для каждого, а затем подсчет точек , используя wcспособность «s для подсчета байт вместо строк, wc -c.
/usr/binбудут хорошо отформатированы (и также не будут содержать пробелов, так что технически вы могли бы даже просто echo * | wc -w), стоит отметить, что все они будут ломаться на именах файлов, содержащих символы новой строки.
ls -lили ls -1мы сломаемся, потому что мы считаем строки, а не слова! findМожет сломаться, но опять же , мы рассчитываем строки не слово.
touch $'foo\nbar'в пустом каталоге, за которым следует одна из ваших команд (скажем ls -1 | wc -l), будет отчет о двух файлах, а не об одном - потому что этот файл состоит из двух строк wc. Если не lsзаменить символы новой строки каким-либо другим символом (я не думаю, что это так, но опять же я не в состоянии проверить прямо сейчас).
wc -cэто проблема при подсчете периодов?
Если вы хотите получить рекурсивную разбивку числа файлов каждого типа под некоторым каталогом, с помощью GNU find, вы можете сделать:
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 (&)/'
В /usr/binмоей системе это дает:
3727 regular files
710 symbolic links
На /dev:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
Для символических ссылок, если вы предпочитаете считать их типом файла, на который они указывают, а не его symbolic links, вы можете изменить его на:
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 (&)/'
Который сейчас дает для моего /usr/bin:
1 directories
4434 regular files
2 broken symbolic links
(неработающая символическая ссылка - это символическая ссылка на файл, для которой findневозможно определить тип, либо потому, что файл не существует, либо находится в каталоге, к которому у вас нет доступа, либо в разрешении пути к файлу есть цикл В моем случае те 2, где символические ссылки на файлы, которые сейчас ушли).
Никто из тех не считается .и ... Если вы хотите, чтобы они были включены (почему вы?), Нет другого пути, findкроме как предположить, что они есть для каждого каталога и подсчитывать их систематически:
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 (&)/'
Который затем дает на моем /usr/bin:
2 directories
3727 regular files
710 symbolic links
Если у вас нет доступа к GNU find, вы можете переписать первый как:
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
Теперь, строго говоря, мы не считали файлы, а только записи в каталогах . Каталог, как /usr/binправило, имеет несколько записей, которые указывают на один и тот же файл. Например, здесь у меня есть:
$ 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
Это 3 записи каталога (или имена файлов или жесткие ссылки) к одному и тому же файлу (с индексом 672252. Для подсчета файлов вместо записей каталога и с помощью GNU findи GNU uniq(игнорирование .и ..файлы, которые в любом случае являются жесткими ссылками на другие каталоги):
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 (&)/'
По моему /usr/bin, это дает:
3711 regular files
710 symbolic links
Вы не сказали, хотите ли вы, чтобы все файлы находились в / usr / bin рекурсивно или просто под первым уровнем. Кроме того, как вы собираетесь получить слова, которые вы рассчитываете? Обычный способ узнать это запустить find в wc. Как это: найти / usr / bin | wc -l Find перечислит там все, каталоги и файлы. Wc -l подсчитает все строки в выводе find. Это классное задание? Это нормально, если это так, но мне было интересно, зачем вам нужна эта информация, чтобы я мог более тщательно адаптировать ответ. Пожалуйста, дайте мне знать, если вам нужно больше. ребро
В баш, без внешних инструментов.
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
В bash, без внешних инструментов и рекурсии.
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
.ни ..записи, ни записи. Вы можете хотеть избавиться от неоднозначности файла против обычного файла.