Как я могу использовать счетчик слов ( 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
.
ни ..
записи, ни записи. Вы можете хотеть избавиться от неоднозначности файла против обычного файла.