CLI AI

Посчитать файлы в папке: рекурсивно и по типам

2026-07-25

find . -type f | wc -l считает все файлы внутри текущего каталога вместе с подпапками и не считает сами каталоги. Интереснее обычно разбивки — по расширениям и по подпапкам, — и есть один случай, когда wc -l врёт: имя файла с переносом строки.

1. Сколько файлов всего

clai
$ clai сколько файлов в этой папке и во всех вложенных→ find . -type f | wc -l20

-type f отбрасывает каталоги и симлинки, поэтому число что-то значит. ls | wc -l в той же папке ответит 3: он видит только верхний уровень и считает каталоги как записи.

2. Разбивка по расширениям

clai
$ clai посчитай файлы по расширениям→ find . -type f -name '*.*' | sed 's/.*\.//' | sort | uniq -c | sort -rn      7 jpg      6 py      4 md      1 txt      1 png      1 bin

Обычно это и есть настоящий вопрос: из чего вообще состоит каталог. -name '*.*' отбрасывает файлы без расширения — без него sed вернёт для них имя целиком.

3. Разбивка по подпапкам

clai
$ clai посчитай файлы в каждой подпапке→ for d in */; do printf '%5s %s\n' "$(find "$d" -type f | wc -l)" "$d"; done    3 docs/    8 img/    7 src/

Цикл по каталогам верхнего уровня со счётом внутри каждого, рекурсивно. Скрытые каталоги под */ не подпадают — поэтому сумма меньше общего числа.

4. Без скрытых файлов

clai
$ clai посчитай файлы, пропуская скрытые→ find . -type f -not -path '*/.*' | wc -l18

20 против 18 — ровно два точечных файла. -not -path '*/.*' заодно выкидывает всё содержимое скрытых каталогов вроде .git, а обычно именно это и имелось в виду.

5. Ловушка: перенос строки в имени

clai
$ clai посчитай файлы надёжно, даже если в именах есть переносы строк→ find . -type f -printf '.' | wc -c21

Проверено на файле, имя которого занимает две строки: find . -type f | wc -l в том же каталоге отвечает 22. wc -l считает строки, а не файлы. -printf '.' печатает по точке на файл, и счёт снова верный. Переносимый вариант без GNU-расширений — find . -type f -print0 | tr -dc '\0' | wc -c.

6. Файлы и каталоги одной строкой

clai
$ clai покажи сколько здесь файлов и сколько каталогов→ printf 'files: %s\ndirs: %s\n' "$(find . -type f | wc -l)" "$(find . -type d | wc -l)"

-type d считает и сам текущий каталог, поэтому каталогов всегда на один больше, чем ожидаешь.

Gotchas

  • ls | wc -l считает не то. Он не заходит в подпапки, зато считает каталоги и пропускает точечные файлы. На заданный вопрос отвечает find -type f.
  • wc -l ломается на переносах строк в именах. Проверено: файлов 21, ответ 22. Если каталог пришёл извне — от пользователей, из архива, от парсера, — считайте через -printf '.' или -print0.
  • find . заходит в скрытые каталоги. В репозитории один .git добавит к итогу тысячи файлов. Фильтруйте через -not -path '*/.*', иначе число ничего не значит.

Related questions

Как посчитать только верхний уровень? find . -maxdepth 1 -type f | wc -l не спускается в подпапки.

Как посчитать файлы одного типа? find . -type f -name '*.log' | wc -l. Регистр важен; если не нужен — -iname.

А если нужен объём, а не число? du -sh . даёт суммарный размер, du -h --max-depth=1 | sort -h — разбивку по подпапкам.

See also

CliAI превращает «сколько файлов по типам» в готовый конвейер и показывает его до запуска. Поставить одной строкой.