Найти количество файлов в каталоге
есть ли какой-либо метод в Linux для вычисления количества файлов в каталоге (то есть непосредственных потомков) в O(1) (независимо от количества файлов) без необходимости перечислять каталог первым? Если нет O (1), Есть ли разумно эффективный способ?
Я ищу альтернативу ls | wc -l
.
8 ответов
readdir не так дорого, как вы можете подумать. Умение избежать статирования каждого файла и (необязательно) сортировки выходных данных ls.
/bin/ls -1U | wc -l
избегает псевдонимов в вашей оболочке, не сортирует вывод и перечисляет 1 файл на строку (не обязательно при транспортировке вывода в wc).
исходный вопрос можно перефразировать, как "структура данных хранилища количество записей?- на что ответ отрицательный. Нет более эффективный способ подсчета файлов, чем readdir(2)/getdents (2).
можно получить количество подкаталогов данного каталога, не пересекая весь список, stat'ING(stat(1) или stat (2)) данного каталога и наблюдая количество ссылок на этот каталог. Данный каталог с N дочерними каталогами будет иметь количество ссылок N+2, Одна ссылка для ".."запись каждого подкаталога, плюс два для"." и." .- записи данного справочника.
однако невозможно получить количество всех файлов (будь то обычные файлы или подкаталоги), не пересекая весь список - это правильно.
команда" /bin/ls-1U " не получит все записи. Он получит только те записи справочника, которые не начинаются с точки (.) характер. Например, это не будет считаться ".файл "профиль" находится во многих каталогах login $HOME.
можно использовать команду "/bin/ls-f" или команду "/bin/ls-Ua", чтобы избежать сортировки и получить все записи.
возможно к сожалению, для ваших целей команда" /bin/ls-f "или команда" /bin/ls-Ua "также будут считать"." и." ."записи, которые есть в каждом каталоге. Вам придется вычесть 2 из подсчета, чтобы избежать подсчета этих двух записей, например, в следующем:
expr `/bin/ls -f | wc -l` - 2 # Those are back ticks, not single quotes.
параметр --format=single-column (-1) не требуется в команде "/bin/ls-Ua" при передаче вывода "ls", как в этом случае в "wc". Команда "ls" автоматически запишет свой вывод в один столбец, если выход не является терминалом.
на на ls
не в POSIX, а в OS X's ls
это имеет другое значение, чем GNU ls
, который он делает -t
и -l
используйте время создания вместо времени модификации. -f
находится в POSIX как расширение XSI. Руководство GNU ls
описание -f
as do not sort, enable -aU, disable -ls --color
и -U
as do not sort; list entries in directory order
.
POSIX описывает -f
такой:
заставить каждый аргумент интерпретироваться как каталог и перечислите имя, найденное в каждом слоте. Эта опция должна отключить
-l
,-t
,-s
и-r
, и включится-a
; порядок-это порядок, в котором записи отображаются в каталоге.
команды типа ls|wc -l
дайте неправильный результат, когда имена файлов содержат новые строки.
в zsh вы можете сделать что-то вроде этого:
a=(*(DN));echo ${#a}
D
(glob_dots
) включает в себя файлы, имя которых начинается с точки и N
(null_glob
) приводит к тому, что команда не приводит к ошибке в пустом каталоге.
или то же самое в Баш:
shopt -s dotglob nullglob;a=(*);echo ${#a[@]}
если IFS
содержит цифры ASCII, добавьте двойные кавычки вокруг ${#a[@]}
. Добавить shopt -u failglob
обеспечить failglob
не установлено.
портативный вариант-использовать find
:
find . ! -name . -prune|grep -c /
grep -c /
можно заменить на wc -l
если имена файлов не содержат переводов строк. ! -name . -prune
является портативной альтернативой -mindepth 1 -maxdepth 1
.
или вот еще одна альтернатива, которая обычно не включает файлы, имя которых начинается с точки:
set -- *;[ -e "" ]&&echo "$#"
команда выше, однако, включает файлы, имя которых начинается с периода, когда опция, как dotglob
в bash или glob_dots
в zsh установлен. Когда *
не соответствует файлу, команда приводит к ошибке в zsh с настройками по умолчанию.
я использовал эту команду..работает как шарм..только чтобы изменить maxdepth..то есть подкаталоги
find * -maxdepth 0 -type d -exec sh -c "echo -n {} ' ' ; ls -lR {} | wc -l" \;
Я думаю, что вы можете иметь больше контроля над этим, используя find
:
find <path> -maxdepth 1 -type f -printf "." | wc -c
-
find -maxdepth 1
не будет углубляться в иерархию файлов. -
-type f
позволяет фильтровать только файлы. Аналогично, вы можете использовать-type d
для каталогов. -
-printf "."
печатает точку для каждого совпадения. -
wc -c
подсчитывает символы, поэтому он подсчитывает точки, созданныеprint
... что означает подсчет количества файлов, существующих в данном путь.
насколько я знаю, лучшей альтернативы нет. Эта информация может быть вне темы для этого вопроса, и вы уже знаете, что под Linux (в целом под Unix) каталоги-это просто специальный файл, который содержит список других файлов (я понимаю, что точные детали будут зависеть от конкретной файловой системы, но это общая идея). И нет вызова, чтобы найти общее количество записей, не пересекая весь список. Пожалуйста, поправьте меня, если я ошибаюсь.