Как подсчитать все файлы рекурсивно по каталогам


48

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

du -sh /*

что даст мне пространство, используемое в каталогах вне root, но в этом случае я хочу количество файлов, а не размер.



Я думаю, что «сколько файлов находится в подкаталогах в этих подкаталогах» - сложная конструкция. Если более четко указать, что вы хотите, вы можете получить ответ, который отвечает всем требованиям.
Стивен Д

@ Стивен, не стесняйся переписать его ... Я подумал, что мой пример du -sh /*прояснил, как я хотел, чтобы счет работал. То же самое, просто посчитать файлы, а не байты.
ксенотеррацид

Как вы упомянули об использовании инода, я не понимаю, хотите ли вы сосчитать количество файлов или количество используемых инодов. Они отличаются, когда в файловой системе присутствуют жесткие ссылки. Большинство, если не все, ответы дают количество файлов. Не используйте их на резервном диске Apple Time Machine.
Mouviciel

@mouviciel, это не используется на резервном диске, и да, я полагаю, они могут отличаться, но в среде, где я нахожусь, очень мало жестких ссылок, технически мне просто нужно почувствовать это. выяснить, где кто-то сжигает там квоту.
ксенотеррацид

Ответы:


61
find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done

Спасибо Жилю и ксенотеррациду за исправления безопасности / совместимости.

Первая часть: find -maxdepth 1 -type dвернет список всех каталогов в текущем рабочем каталоге. Это по трубопроводу ...

Вторая часть: while read -r dir; doначинается цикл while - пока канал, входящий в while, открыт (то есть до тех пор, пока не будет отправлен весь список каталогов), команда read поместит следующую строку в переменную "dir". Тогда это продолжается ...

Третья часть: printf "%s:\t" "$dir";напечатает строку в «$ dir» (которая содержит одно из имен каталогов) с последующей вкладкой.

Четвертая часть: find "$dir -f file"составляет список всех файлов внутри имени каталога, хранящихся в «$ dir». Этот список отправляется ..

Пятая часть: wc -l;подсчитывает количество строк, которые отправляются на его стандартный ввод.

Последняя часть: doneпросто завершает цикл while.

Таким образом, мы получаем список всех каталогов в текущем каталоге. Для каждого из этих каталогов мы генерируем список всех файлов в нем, чтобы мы могли сосчитать их все, используя wc -l. Результат будет выглядеть так:

./dir1: 234
./dir2: 11
./dir3: 2199
...

Всегда используйте read -rкак обычное readсредство для обратного слеша. Тогда echo -en "$dir:\t"снова будет искажать обратную косую черту; простое исправление - использовать printf '%s:\t' "$dir"вместо этого. Далее $dirдолжно быть "$dir"( всегда используйте двойные кавычки вокруг подстановок переменных ).
Жиль "ТАК - перестань быть злым"

изменено в соответствии с предложениями @Gilesfind -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" | wc -l; done
xenoterracide

2
Я добавляю sort -n -r -k2в конце этого, для многих каталогов, чтобы я знал, где больше всего используется
xenoterracide

Четвертая часть: find "$ dir" составляет список всех файлов внутри имени каталога, содержащихся в "$ dir". Вы забыли добавить, -type fчтобы сделать это список файлов:find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done
Кшиштоф Boduch

1
Я не заставляю это работать на macOS Sierra 10.12.5. illegal option -- mв findкоманде. Я изменил это на find . -maxdepth ...и получил его на работу.
Джефф

15

Попробуйте find . -type f | wc -l, он будет считать все файлы в текущем каталоге, а также все файлы в подкаталогах. Обратите внимание, что все каталоги не будут учитываться как файлы, только обычные файлы.


13

Вот компиляция некоторых полезных команд листинга (повторное хеширование на основе кода предыдущих пользователей):

Список папок с количеством файлов:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); printf "%4d : %s\n" $n "$dir"; done

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

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Список папок с количеством подпапок:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; printf "%4d : %s\n" $n "$dir"; done

Список папок с ненулевым количеством подпапок:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Список пустых папок:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -eq 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Список непустых папок с количеством контента:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

И между прочим .. если вы хотите, чтобы выходные данные любой из этих команд списка были отсортированы по количеству элементов .. передайте команду в сортировку: "a-list-command" | sort -n
DolphinDream

12

Пытаться:

find /path/to/start/at -type f -print | wc -l

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

find `find /path/to/start/at -mindepth 1 -maxdepth 1 -type d -print` -type f -print | wc -l

+1 за что-то | wc -l ... подсчет слов - такой хороший маленький инструмент
Johan

да, но это только 1 каталог .... Я хотел бы получить счетчик для всех каталогов в каталоге, и я не хочу запускать его отдельно каждый раз ... конечно, я полагаю, я мог бы использовать цикл ... но я ленивый.
ксенотеррацид

findпо умолчанию работает рекурсивно через все подкаталоги. Если вы хотите, чтобы он работал в нескольких местах, вы можете указать все их между findи -type.
Дидье Троссет

тот второй, конечно, не работает .... Я попробовал это / дома. Я получил 698035 . Я должен увидеть около 6 номеров.
ксенотеррацид

Это работает для меня - вы уверены, что у вас есть только 6 файлов под /home? Я был бы на 100% уверен, что вы этого не сделаете.
Плачь Хавок

4

Следующее решение подсчитывает фактическое количество используемых inode, начиная с текущего каталога:

find . -print0 | xargs -0 -n 1 ls -id | cut -d' ' -f1 | sort -u | wc -l

Чтобы получить количество файлов одного подмножества, используйте:

find . | wc -l

Для решений, исследующих только подкаталоги, без учета файлов в текущем каталоге, вы можете обратиться к другим ответам.


1
Хорошая идея, учитывая жесткие ссылки. Предполагая , что GNU находку, вам не нужно так много шагов: find -printf '%i\n' | sort -u | wc -l. Если вы хотите быть портативным, вам нужно find . -exec ls -id {} + | cut …вместо этого.
Жиль "ТАК - перестань быть злым"

2

OS X 10.6 душит команду в принятом ответе, потому что она не указывает путь для find. Вместо этого используйте:

find . -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done

2

Я знаю, что опаздываю на вечеринку, но я верю, что bashв некоторых ситуациях это чистое (или другой оболочка, которая принимает двойной звездный шар) может быть намного быстрее:

shopt -s globstar    # to enable ** glob in bash
for dir in */; do a=( "$dir"/**/* ); printf "%s\t%s\n" "$dir:" "${#a[*]}"; done

выход:

d1/:    302
d2/:    24
d3/:    640
...

1

Попробуйте это:

find -type d -print0 | xargs -0 -I {} sh -c 'printf "%s\t%s\n" "$(find "{}" -maxdepth 1 -type f | wc -l)" "{}"'

Он должен работать нормально, если в именах файлов нет новых строк.


слишком рекурсивный ... Я хочу видеть только верхний уровень, где он подытоживает все, что находится под ним. в итоге ... это заканчивается печатью каждого каталога.
ксенотеррацид

@xenoterracide: попробуйте добавить -maxdepth 1сразу после первого find. Если вы хотите включить в свой счетчик количество подкаталогов, удалите их -type fв конце (это должно было быть в ! -type dлюбом случае, чтобы были включены все файлы, не относящиеся к каталогам).
Деннис Уильямсон

1

Если у вас есть ncduустановленный cпродукт ( необходимый для очистки), просто введите «Переключить отображение количества дочерних элементов». И C"Сортировать по элементам".


1
лол, это должен быть самый верный ответ :)
x-yuri

0

du --inodes

Я не уверен, почему никто (включая меня) не знал о:

du --inodes
--inodes
      list inode usage information instead of block usage

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

Дальнейшая информация

Если вы НЕ хотите повторяться (что может быть полезно в других ситуациях), добавьте

-S, --separate-dirs
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.