Краткий ответ:
\ls -afq | wc -l
(Это включает .
и ..
, так что вычтите 2.)
Когда вы перечисляете файлы в каталоге, могут произойти три общие вещи:
- Перечисление имен файлов в каталоге. Это неизбежно: нет способа подсчитать файлы в каталоге, не перечислив их.
- Сортировка имен файлов. Подстановочные знаки оболочки и
ls
команда делают это.
- Вызов
stat
для получения метаданных о каждой записи каталога, например, является ли он каталогом.
№ 3, безусловно, самый дорогой, потому что он требует загрузки индекса для каждого файла. Для сравнения, все имена файлов, необходимые для # 1, компактно хранятся в нескольких блоках. # 2 тратит некоторое процессорное время, но часто это не прерывает сделки.
Если в именах файлов нет новых строк, простой ls -A | wc -l
говорит вам, сколько файлов в каталоге. Помните, что если у вас есть псевдоним для ls
, это может вызвать вызов stat
(например, ls --color
или вам ls -F
необходимо знать тип файла, для которого требуется вызов stat
), поэтому из командной строки вызывайте command ls -A | wc -l
или \ls -A | wc -l
избегайте псевдонима.
Если в имени файла есть новые строки, то будут ли новые строки перечислены или нет, зависит от варианта Unix. GNU coreutils и BusyBox по умолчанию отображают ?
новую строку, поэтому они в безопасности.
Вызовите ls -f
список записей без сортировки их (# 2). Это автоматически включается -a
(по крайней мере, в современных системах). -f
Вариант в POSIX , но с дополнительным статусом; большинство реализаций поддерживают его, но не BusyBox. Опция -q
заменяет непечатаемые символы, включая символы новой строки, на ?
; это POSIX, но не поддерживается BusyBox, поэтому пропустите его, если вам нужна поддержка BusyBox за счет перерасчета файлов, имя которых содержит символ перевода строки.
Если в каталоге нет подкаталогов, то большинство версий find
не будут вызывать stat
его записи (листовая оптимизация каталога: каталог с числом ссылок 2 не может иметь подкаталоги, поэтому find
не нужно искать метаданные записей, если только состояние такое как -type
требует). Таким образом find . | wc -l
, это переносимый и быстрый способ подсчета файлов в каталоге, при условии, что в каталоге нет подкаталогов и что ни одно имя файла не содержит символ новой строки.
Если в каталоге нет подкаталогов, но имена файлов могут содержать символы новой строки, попробуйте один из них (второй должен быть быстрее, если он поддерживается, но может быть не так заметно).
find -print0 | tr -dc \\0 | wc -c
find -printf a | wc -c
С другой стороны, не используйте, find
если в каталоге есть подкаталоги: даже find . -maxdepth 1
вызовы stat
для каждой записи (по крайней мере, с GNU find и BusyBox find). Вы избегаете сортировки (# 2), но платите цену поиска по индоду (# 3), который снижает производительность.
В оболочке без внешних инструментов вы можете запустить подсчет файлов в текущем каталоге с помощью set -- *; echo $#
. Это пропускает точечные файлы (файлы, чье имя начинается с .
) и сообщает 1 вместо 0 в пустой директории. Это самый быстрый способ подсчета файлов в небольших каталогах, поскольку он не требует запуска внешней программы, но (за исключением zsh) тратит время на большие каталоги из-за шага сортировки (# 2).
В bash это надежный способ подсчета файлов в текущем каталоге:
shopt -s dotglob nullglob
a=(*)
echo ${#a[@]}
В ksh93 это надежный способ подсчета файлов в текущем каталоге:
FIGNORE='@(.|..)'
a=(~(N)*)
echo ${#a[@]}
В zsh это надежный способ подсчета файлов в текущем каталоге:
a=(*(DNoN))
echo $#a
Если у вас есть mark_dirs
набор опций, убедитесь , чтобы выключить его: a=(*(DNoN^M))
.
В любой оболочке POSIX это надежный способ подсчета файлов в текущем каталоге:
total=0
set -- *
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- .[!.]*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- ..?*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
echo "$total"
Все эти методы сортируют имена файлов, кроме zsh.
ls -l|wc -l
будет отключен на единицу из-за общего количества блоков в первой строкеls -l
вывода