Если я это сделаю ls -1 target_dir | wc -l
, я получу количество файлов в каталоге. Я нахожу это немного громоздким. Есть ли более элегантный или лаконичный способ?
ubuntu
command-line
filesystems
codecowboy
источник
источник
ls
уже дает общее количество, так как насчетls -l | head -1
? Сделайте псевдоним, если вы хотите что-то короче.ls -l
указывает на общий размер файлов, а не на количество файлов.ls | wc -l
это даст вам неправильный счет, если какие-либо имена файлов содержат символы новой строки.stat -c %h .
дает ту же информацию, что иls -ld . | cut -d" " -f 2
Ответы:
Предполагая bash 4+ (который есть в любой поддерживаемой версии Ubuntu):
Назовите это как
num_files [dir]
.dir
не является обязательным, в противном случае он использует текущий каталог. Ваша оригинальная версия не учитывает скрытые файлы, так же как и это. Если ты этого хочешь,shopt -s dotglob
раньшеset -- *
.Ваш исходный пример содержит не только обычные файлы, но также каталоги и другие устройства - если вы действительно хотите только обычные файлы (включая символические ссылки на обычные файлы), вам необходимо проверить их:
Если у вас есть GNU find, что-то вроде этого также является опцией (обратите внимание, что это включает в себя скрытые файлы, чего не делала ваша оригинальная команда):
(измените
-type
на,-xtype
если вы также хотите считать символические ссылки на обычные файлы).источник
set
выйдет ли из строя, если файлов очень много? Я думаю, что вам, возможно, придется использоватьxargs
и некоторый суммирующий код, чтобы это работало в общем случае.shopt -s dotglob
если вы хотите, чтобы файлы, начинающиеся с,.
были подсчитаныset
что при таких обстоятельствах ничего не получится, так как мы на самом деле не делаемexec
. То есть, в моей системеgetconf ARG_MAX
выдает 262144, но если я это сделаюtest_arg_max() { set -- {1..262145}; echo $#; }; test_arg_max
, он с радостью отвечает 262145.-maxdepth
- это не POSIX.f=(target_dir/*);echo ${#f[*]}
корректно работает для файла с пробелами, символами новой строки и т. д. в имени.
источник
ls
является многостолбцовым, только если он выводится непосредственно на терминал, вы можете удалить опцию «-1», вы можете убратьwc
опцию «-l», прочитать только первое значение (ленивое решение, не будет использоваться для юридических доказательств, уголовные расследования, критические задачи, тактические операции ..).источник
wc
чтобы получить количество файлов даже в тривиальном случае, так как же это решение?target
это глоб, который при расширении включает в себя некоторые вещи, которые начинаются с дефисов. Например, создайте новый каталог, зайдите в него и сделайтеtouch -- {1,2,3,-a}.txt && ls *|wc
(NB: используйте,rm -- *.txt
чтобы удалить эти файлы.)wc -l
? В противном случае вы получите новые строки, слова и количество байтовls
вывода. Вот что сказал Дэвид Ричерби: «Вы должны разобрать это снова.wc
нет аргументов, вам не нужно анализировать, если ваш мозг знает, что первым аргументом является перевод строки.Если это лаконичность вы после (а не точная правильности при работе с файлами с новой строкой в их именах, и т.д.), я рекомендую просто искажения
wc -l
вlc
( «число строк»):Как уже отмечали другие, вам не нужна эта
-1
опцияls
, поскольку она автоматическиls
записывает данные в канал. (Если у вас нетls
псевдонима, чтобы всегда использовать режим столбца. Я видел это раньше, но не очень часто.)В
lc
общем, псевдоним довольно удобен, и для этого вопроса, если вы посмотрите на случай «посчитать текущий каталог», онls|lc
будет как можно более кратким.источник
Пока что Аарон - единственный подход, более краткий, чем ваш. Более правильная версия вашего подхода может выглядеть так:
Это рекурсивно перечисляет все файлы - не каталоги - по одному на строку, включая файлы .dotfile под текущим каталогом, используя при необходимости глобусы оболочки для замены непечатаемых символов. grep отфильтровывает любые списки родительских каталогов или .. или * / или пустые строки - поэтому в файле должна быть только одна строка - общее количество, которое возвращает вам grep. Если вы хотите включить дочерние каталоги, сделайте:
Удалите
-R
в любом случае, если вы не хотите рекурсивных результатов.источник
find
. Если вам нужен только счет, это должно сработать:find -mindepth 1 -maxdepth 1 -printf '\n'|wc -l
(уберите регуляторы глубины, чтобы получить рекурсивные результаты).find . \! -name . -prune | wc -l
- что, конечно, все еще не работает.printf
инструкция печатает постоянную строку (новую строку), которая вообще не включает имя файла, поэтому результаты не зависят от каких-либо странных имен файлов. Этот трюк не может быть сделан вообще с,find
который не поддерживаетprintf
, конечно.find .//. \!. -name . -prune | grep -c '^\.//\.'
/
Будучи единственным другим символом, который не может появиться в именах файлов,.//.
последовательность гарантированно появится ровно один раз для каждого файла, верно? пара вопросов, хотя - почему.//.
и почему-prune
? когда это будет отличаться отfind . \! -name . | grep -c '^\.'
? (Я полагаю, что это.
ваша\!.
опечатка.)