Краткий ответ:
\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вывода