Вопрос

Существует ли какой -либо метод в Linux для расчета количества файлов в каталоге (то есть непосредственных детей) в O (1) (независимо от количества файлов) без необходимости сначала перечислить каталог? Если не O (1), есть ли разумно эффективным способом?

Я ищу альтернативу ls | wc -l.

Это было полезно?

Решение

Readdir не так дорого, как вы думаете. Круп, избегая статистики каждого файла и (необязательно) сортирует вывод LS.

/bin/ls -1U | wc -l

избегает псевдонимов в вашей оболочке, не сортирует выходные данные и перечисляет 1 файл на линию (не требует строго необходимости при передаче вывода в WC).

Первоначальный вопрос может быть перефразирован как «хранят ли структура данных каталога подсчет количества записей?», На что ответ - нет. Нет более эффективного способа подсчета файлов, чем readdir (2)/getDents (2).

Другие советы

Можно получить количество подкаталогов данного каталога, не пройдя весь список по статистике (стат (1) или статистике (2)) данного каталога и соблюда количества ссылок на этот каталог. В данном каталоге с N Kids Directory будет количество ссылок N+2, одна ссылка для «..» в записи каждого подкаталера, плюс два для «». и ".." Записи данного каталога.

Однако нельзя получить количество всех файлов (будь то обычные файлы или подкаталогов), не пройдя весь список - это правильно.

Команда "/bin/ls -1u" не получит все записи. Это получит Только Эти записи каталога, которые не начинаются с символа DOT (.). Например, он не будет считать файл «.profile», найденный во многих домашних каталогах Login $.

Можно использовать либо команду "/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 = одноконкурм (-1) не требуется в команде «/bin/ls -ua» при пропуске вывода «LS», как в «WC» в данном случае. Команда «LS» автоматически записывает свой вывод в одном столбце, если вывод не является терминалом.

А -U вариант для ls не в Posix, а в OS X ls он имеет другое значение от GNU ls, это то, что он делает -t и -l Используйте время создания вместо времени модификации. -f находится в Posix как расширение XSI. Руководство GNU ls описывает -f в виде do not sort, enable -aU, disable -ls --color и -U в виде 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) приводит к тому, что команда не приводит к ошибке в пустом каталоге.

Или то же самое в Bash:

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 "$1" ]&&echo "$#"

Приведенная выше команда включает в себя файлы, имя которого начинается с периода, когда такая опция dotglob в Bash или glob_dots в ZSH установлен. Когда * Матч нет файла, команда приводит к ошибке в ZSH с настройками по умолчанию.

Я использовал эту команду .. заработанные как обаяние .. только чтобы изменить максимальный

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) есть просто специальный файл, который содержит список других файлов (я понимаю, что точные данные будут зависеть от конкретного файла Система, но это общая идея). И нет звонка, чтобы найти общее количество записей, не пройдя весь список. Пожалуйста, сделайте меня корректным, если я ошибаюсь.

Для количества всего файла в текущем каталоге попробуйте это:

ls -lR * | wc -l

Используйте LS -1 | wc -l

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top