Рекурсивный подсчет файлов в каталоге Linux

730

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

Я нашел это:

find DIR_NAME -type f ¦ wc -l

Но когда я запускаю это, он возвращает следующую ошибку.

найти: пути должны предшествовать выражению: ¦

Роберт Бакли
источник
64
Вы путаете ломаную полосу ¦(ASCII 166) с вертикальной чертой |(ASCII 124), используемой для конвейера UNIX .
Скиппи ле Гран Гуру
7
@SkippyleGrandGourou Разве это не называется труба?
DaveStephens
27
@DaveStephens Да, это также называется. Это также называют ударом Шеффера, вертибаром, vbar, палкой, вертикальной линией, вертикальной косой чертой, баром, обелиском, глидусом.
Эмлай
64
@zenith Я просто называю это Боб.
Кристофер
15
В RFC20 это называется «вертикальная линия». «Трубка» - это имя оператора оболочки, а не имя символа. Точно так же, как *символ «звездочка» ASCII, но «время» в некоторых других контекстах.
тонкий

Ответы:

1329

Это должно работать:

find DIR_NAME -type f | wc -l

Объяснение:

  • -type f включать только файлы.
  • |( и не¦ ) перенаправляет findстандартный вывод wcкоманды на стандартный ввод команды.
  • wc(сокращение от количества слов) подсчитывает новые строки, слова и байты на входе ( документы ).
  • -l считать только переводы строк.

Ноты:

  • Замените DIR_NAMEна, .чтобы выполнить команду в текущей папке.
  • Вы также можете удалить, -type fчтобы включить каталоги (и символические ссылки) в число.
  • Возможно, эта команда будет пересчитана, если имена файлов могут содержать символы новой строки.

Объяснение того, почему ваш пример не работает:

В показанной вами команде вы не используете «Pipe» ( |) для соединения двух команд, а разбитую панель ( ¦), которую оболочка не распознает как команду или что-то подобное. Вот почему вы получаете это сообщение об ошибке.

paulsm4
источник
27
fВ -type fстендах для файлов и wc -lдля слов строк.
Серж Строобандт
3
Удалите, -type fчтобы включить каталоги в счетчик
phatblat
3
Там нет необходимости для -printфлага
Золтан
3
Если есть вероятность того, что имена файлов содержат символ новой строки, вы можете использовать -print0флаг.
gaboroncancio
2
@gaboroncancio Это не поможет, если в какой-то реализации wcнет опции для чтения нулевого завершенного списка. Смотрите мой ответ для альтернативы.
Восстановите Монику, пожалуйста,
100

Для текущего каталога:

find -type f | wc -l
Абхишек Маурья
источник
5
Это решение не учитывает имя файла, содержащее переводы строк.
Кусалананда
2
Для текущего каталога вам даже не нужен.
baptx
1
На самом деле, на некоторых платформах, вы действительно нужно прописатьfind .
tripleee
1
@Kusalanandra Ваш комментарий относится почти к каждому ответу здесь.
tripleee
69

Если вы хотите указать количество файлов в каждом каталоге под вашим текущим каталогом:

for i in */ .*/ ; do 
    echo -n $i": " ; 
    (find "$i" -type f | wc -l) ; 
done

Это может идти все в одной строке, конечно. В скобках указывается, чей вывод wc -lпредполагается просматривать ( find $i -type fв данном случае).

Грег Белл
источник
7
Он может застрять в каталогах с пробелами в их именах. Изменение первой строки, чтобы find . -maxdepth 1 -type d -print0 | while IFS= read -r -d '' i ; doисправить это. См. Как я могу прочитать файл (поток данных, переменную) построчно (и / или поле за полем)?
Арка Стэнтон
4
Использование findдля внешнего цикла - просто ненужное осложнение. for i in */; do`
tripleee
function countit {for i in $ (find. -maxdepth 1 -type d); do file_count = $ (find $ i -type f | wc -l); echo "$ file_count: $ i"; сделанный }; граф | sort -n -r
Schneems
Наконец это то, что мне было нужно. В моих папках тысячи файлов, поэтому распечатывать их с помощью дерева или чего-либо еще нельзя
lesolorzanov
Это включает в себя ../ и, похоже, не продвигается вперед, то есть не регрессивно.
Даниэль Лефевр
50

Ты можешь использовать

$ tree

после установки пакета дерева с

$ sudo apt-get install tree

(на компьютере с Debian / Mint / Ubuntu Linux).

Команда показывает не только количество файлов, но и количество каталогов отдельно. Опция -L может использоваться для указания максимального уровня отображения (который по умолчанию является максимальной глубиной дерева каталогов).

Скрытые файлы также могут быть включены путем предоставления -aопции.

лев
источник
4
На самом деле это самый простой способ увидеть количество каталогов и файлов.
Лорем Ипсум Долор
11
Со страницы руководства: по умолчанию дерево не печатает скрытые файлы . Вы должны предоставить -aвозможность включить их.
Eee
3
Чтобы установить это на macOS, используйте brewи запускайте brew install tree, предпочтительно после запуска brew update.
Ашиш Ахаджа
4
Он также печатает все имена файлов, поэтому он будет медленным, если у вас много файлов.
Франк Дернонкур
2
Вау, очень хороший инструмент, он может печатать папки в цвете, перечислять только папки, выводить в формате JSON. Он может перечислить 34 тыс. Папок и 51 тыс. Файлов за несколько секунд. Olé!
Brasofilo
46

На моем компьютере rsyncэто немного быстрее, чем find | wc -lв принятом ответе:

$ rsync --stats --dry-run -ax /path/to/dir /tmp

Number of files: 173076
Number of files transferred: 150481
Total file size: 8414946241 bytes
Total transferred file size: 8414932602 bytes

Вторая строка содержит количество файлов 150 481 в приведенном выше примере. В качестве бонуса вы также получаете общий размер (в байтах).

Примечания:

  • первая строка - это количество файлов, каталогов, символических ссылок и т. д. вместе взятых, поэтому она больше, чем вторая строка.
  • --dry-run(или -nвариант для краткости) важно на самом деле не передавать файлы!
  • Я использовал -xопцию «не пересекать границы файловой системы», что означает, что если вы выполняете ее /и у вас подключены внешние жесткие диски, она будет считать только файлы в корневом разделе.
Псмит
источник
Мне нравится ваша идея использовать rsync здесь. Я никогда бы не подумал об этом!
Кеол
Спасибо @Qeole, идея не моя, хотя. Несколько лет назад я где-то читал, что rsync - это самый быстрый способ удаления папки с большим количеством файлов и подпапок, поэтому я подумал, что это может быть также быстрый подсчет файлов.
Псмит
1
Пробовал это. После предварительного запуска обоих дважды для заполнения кеша fs find ~ -type f | wc -lпотребовалось 1,7 / 0,5 / 1,33 секунды (real / user / sys). rsync --stats --dry-run -ax ~ /xxxзаняло 4,4 / 3,1 / 2,1 секунды. Это около 500 000 файлов на SSD.
тонкий
Не знаю, какую версию rsync вы использовали, но в 3.1.2 это немного проще для чтения:Number of files: 487 (reg: 295, dir: 192)
mpen
Я использовал rsync по умолчанию в macOS:rsync version 2.6.9 protocol version 29
Псмит
20

Поскольку имена файлов в UNIX могут содержать переводы строк (да, переводы строк), wc -lможет быть слишком много файлов. Я бы напечатал точку для каждого файла и затем посчитал точки:

find DIR_NAME -type f -printf "." | wc -c
hek2mgl
источник
1
Похоже, это единственное решение, которое обрабатывает файлы с символами новой строки в их именах. Upvoted.
Codeforester
2
Привет :) Я люблю переводы строк в именах файлов. Это делает их просто более читабельными.
hek2mgl
Я имею в виду, новые строки в именах файлов, а не содержание!
codeforester
1
Я просто пошутил ... Да, переводы строк в именах файлов всегда должны быть приняты во внимание. Они могут быть получены из вредоносного контента или менее впечатляюще, из опечатки.
hek2mgl
18

Комбинируя несколько ответов здесь, наиболее полезным решением является:

find . -maxdepth 1 -type d -print0 |
xargs -0 -I {} sh -c 'echo -e $(find "{}" -printf "\n" | wc -l) "{}"' |
sort -n

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

Вы можете увеличить число после -maxdepthтого, как подсчитать подкаталоги тоже. Имейте в виду, что это может занять много времени, особенно если у вас очень вложенная структура каталогов в сочетании с большим -maxdepthчислом.

Себастьян Майн
источник
Что с echo -e? Я предполагаю, что вы вставили его, чтобы сложить любые новые строки, но он также будет искажать любые другие нерегулярные пробелы и пытаться развернуть любые символы подстановки, присутствующие дословно в именах файлов. Я бы просто пошел с чем-то вроде find .* * -type d -execdir sh -c 'find . -type f -printf "\n" | wc -l; pwd'и жил с любыми аберрациями в выводе, или, возможно, поиграл с Bash printf "%q"для печати имени каталога.
tripleee
10

Если вы хотите узнать, сколько файлов и подкаталогов существует в текущем рабочем каталоге, вы можете использовать этот однострочный

find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find {} | wc -l) {}' | sort -n

Это будет работать во вкусе GNU, и просто опустите -e в команде echo для Linux BSD (например, OSX).

Santrix
источник
2
Отличное решение! Единственной проблемой, которую я нашел, были каталоги с пробелами или специальными символами. Добавьте цитаты, где используется имя режиссера:find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find "{}" | wc -l) "{}"' | sort -n
Джон Кэри
1
Я немного изменил его, и он довольно хорошо работает для меня:find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo $(find {} | wc -l) \\t {}' | sort -rn | less
Wizek
Мои комментарии к ответу @ Себастьяна применимы и здесь. Использование echo -e(или просто `echo`, как в предыдущем комментарии) для имени каталога без кавычек заменяет одну проблему на другую.
tripleee
8

Если вы хотите избежать ошибок, не позволяйте wc -lвидеть файлы с символами новой строки (которые будут считаться как файлы 2+)

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

> mkdir emptydir && cd emptydir
> touch $'file with EOL(\n) character in it'
> find -type f
./file with EOL(?) character in it
> find -type f | wc -l
2

Так как, по крайней мере, gnu wc, по-видимому, не имеет возможности считывать / считать нулевой завершенный список (кроме файла), самым простым решением будет просто не передавать ему имена файлов, а статический вывод каждый раз, когда файл найден, например, в том же каталоге, что и выше

> find -type f -exec printf '\n' \; | wc -l
1

Или, если ваш findподдерживает

> find -type f -printf '\n' | wc -l
1 
Восстановите Монику, пожалуйста
источник
7

Вы можете использовать команду ncdu. Он будет рекурсивно подсчитывать, сколько файлов содержит каталог Linux. Вот пример вывода:

введите описание изображения здесь

Он имеет индикатор выполнения, что удобно, если у вас много файлов:

введите описание изображения здесь

Чтобы установить его на Ubuntu:

sudo apt-get install -y ncdu

Тест: я использовал https://archive.org/details/cv_corpus_v1.tar (380390 файлов, 11 ГБ) в качестве папки, в которой нужно посчитать количество файлов.

  • find . -type f | wc -l: около 1м20 до завершения
  • ncdu: около 1м20 до завершения
Франк Дернонкур
источник
Это в основном рассчитывает использование диска, а не количество файлов. Эти дополнительные накладные расходы, скорее всего, не нужны. (помимо необходимости установить дополнительный пакет для чего-то, что можно сделать с помощью стандартных утилит POSIX)
hek2mgl
@ hek2mgl Он вычисляет количество файлов, как показано красным на первом скриншоте. На ~ 2 миллиона файлов у меня ушло несколько минут, поэтому скорость не так уж и плоха.
Франк Дернонкур
2
@ hek2mgl Я добавил воспроизводимый тест в ответ, я провел его дважды, и я не увидел никакой разницы между find . -type f | wc -lи ncdu.
Франк Дернонкур
2
да, похоже, что он findнаходится под капотом и выполняет более или менее те же системные вызовы, duчто и серверная часть ncdu. Просто привязал их.
hek2mgl
1
@FranckDernoncourt это понравилось. У меня куча файлов в папке, а индикатор выполнения - это спасение жизни. Спасибо, что поделился!
Компьютерщик
6
tree $DIR_PATH | tail -1

Пример вывода:

5309 каталогов, 2122 файлов

Нестор Уркиса
источник
4

Чтобы определить, сколько файлов в текущем каталоге, вставьте ls -1 | wc -l. Используется wcдля подсчета количества строк (-l)в выводе ls -1. Это не считается точечными файлами. Обратите внимание, что ls -l(это «L», а не «1», как в предыдущих примерах), которое я использовал в предыдущих версиях этого HOWTO, на самом деле даст вам количество файлов, которое на один больше, чем фактическое. Спасибо Кам Неджад за этот пункт.

Если вы хотите считать только файлы и НЕ включать символические ссылки (просто пример того, что еще вы могли бы сделать), вы можете использовать ls -l | grep -v ^l | wc -l(на этот раз «L», а не «1», нам нужен «длинный» список здесь) , grepпроверяет наличие любой строки, начинающейся с «l» (указывает на ссылку), и отбрасывает эту строку (-v).

Относительная скорость: «ls -1 / usr / bin / | wc -l» занимает около 1,03 секунды на незагруженном 486SX25 (/ usr / bin / на этом аппарате имеет 355 файлов). « ls -l /usr/bin/ | grep -v ^l | wc -l» занимает около 1,19 секунд.

Источник: http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x700.html

Софи
источник
2
ls -lнеобходимо выполнить statsyscall для каждого файла, чтобы прочитать его размер, mtime и другие свойства, что медленно. На больших каталогах (более 100 000 файлов) запуск ls -lможет занять несколько минут. Поэтому для подсчета только файлов всегда используйте ls -1 | wc -l.
Marki555
A 486SX25, хороший
cam8001
ls -1может все еще быть медленным в больших каталогах, потому что это должно сортировать файлы. Просто printf '%s\n' *делает то же самое и избегает внешнего lsвызова (который в любом случае проблематичен ), но наиболее эффективным решением является использование команды, которая не выполняет никакой сортировки, такой как find. (Вывод
глобуса
4

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

find YOUR_PATH -name '*.html' -type f | wc -l 

-l это просто для отображения количества строк в выводе.

Леон - Хан Ли
источник
Расширение является частью имени файла и может не представлять файл TYPE
Waxhead
4

С bash:

Создайте массив записей с помощью () и получите счет с помощью #.

FILES=(./*); echo ${#FILES[@]}

Хорошо, это не рекурсивно подсчитывает файлы, но я хотел сначала показать простой вариант. Распространенным вариантом использования может быть создание резервных копий для файла при переворачивании. Это создаст logfile.1, logfile.2, logfile.3 и т. Д.

CNT=(./logfile*); mv logfile logfile.${#CNT[@]}

Рекурсивный счет с globstarвключенным bash 4+ (как упомянуто @tripleee)

FILES=(**/*); echo ${#FILES[@]}

Чтобы рекурсивно получить количество файлов, мы все равно можем использовать find таким же образом.

FILES=(`find . -type f`); echo ${#FILES[@]}
nickl-
источник
Поддержка современных оболочек **/*для рекурсивного перечисления. Это все еще менее эффективно, чем findв больших каталогах, потому что оболочка должна сортировать файлы в каждом каталоге.
tripleee
2

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

Это может быть на порядок быстрее, чем lsили findоснованные подходы, но YMMV.

the8472
источник
2

Для каталогов с пробелами в имени ... (на основе различных ответов выше) - рекурсивно вывести имя каталога с количеством файлов в:

find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done

Пример (отформатирован для удобства чтения):

pwd
  /mnt/Vancouver/Programming/scripts/claws/corpus

ls -l
  total 8
  drwxr-xr-x 2 victoria victoria 4096 Mar 28 15:02 'Catabolism - Autophagy; Phagosomes; Mitophagy'
  drwxr-xr-x 3 victoria victoria 4096 Mar 29 16:04 'Catabolism - Lysosomes'

ls 'Catabolism - Autophagy; Phagosomes; Mitophagy'/ | wc -l
  138

## 2 dir (one with 28 files; other with 1 file):
ls 'Catabolism - Lysosomes'/ | wc -l
  29

Структура каталогов лучше визуализируется с помощью tree:

tree -L 3 -F .
  .
  ├── Catabolism - Autophagy; Phagosomes; Mitophagy/
  │   ├── 1
  │   ├── 10
  │   ├── [ ... SNIP! (138 files, total) ... ]
  │   ├── 98
  │   └── 99
  └── Catabolism - Lysosomes/
      ├── 1
      ├── 10
      ├── [ ... SNIP! (28 files, total) ... ]
      ├── 8
      ├── 9
      └── aaa/
          └── bbb

  3 directories, 167 files

man find | grep mindep
  -mindepth levels
    Do not apply any tests or actions at levels less than levels
    (a non-negative integer).  -mindepth 1 means process all files
    except the starting-points.

ls -p | grep -v /(используется ниже) из ответа 2 по адресу /unix/48492/list-only-regular-files-but-not-directories-in-current-directory

find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done
./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
./Catabolism - Lysosomes: 28
./Catabolism - Lysosomes/aaa: 1

Applcation: я хочу найти максимальное количество файлов среди нескольких сотен каталогов (все глубины = 1) [вывод ниже снова отформатирован для удобства чтения]:

date; pwd
    Fri Mar 29 20:08:08 PDT 2019
    /home/victoria/Mail/2_RESEARCH - NEWS

time find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done > ../../aaa
    0:00.03

[victoria@victoria 2_RESEARCH - NEWS]$ head -n5 ../../aaa
    ./RNA - Exosomes: 26
    ./Cellular Signaling - Receptors: 213
    ./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
    ./Stress - Physiological, Cellular - General: 261
    ./Ancient DNA; Ancient Protein: 34

[victoria@victoria 2_RESEARCH - NEWS]$ sed -r 's/(^.*): ([0-9]{1,8}$)/\2: \1/g' ../../aaa | sort -V | (head; echo ''; tail)

    0: ./Genomics - Gene Drive
    1: ./Causality; Causal Relationships
    1: ./Cloning
    1: ./GenMAPP 2
    1: ./Pathway Interaction Database
    1: ./Wasps
    2: ./Cellular Signaling - Ras-MAPK Pathway
    2: ./Cell Death - Ferroptosis
    2: ./Diet - Apples
    2: ./Environment - Waste Management

    988: ./Genomics - PPM (Personalized & Precision Medicine)
    1113: ./Microbes - Pathogens, Parasites
    1418: ./Health - Female
    1420: ./Immunity, Inflammation - General
    1522: ./Science, Research - Miscellaneous
    1797: ./Genomics
    1910: ./Neuroscience, Neurobiology
    2740: ./Genomics - Functional
    3943: ./Cancer
    4375: ./Health - Disease 

sort -Vэто естественный вид. ... Итак, мое максимальное количество файлов в любой из этих папок (Claws Mail) составляет 4375 файлов. Если бы я оставил на клавиатуре ( https://stackoverflow.com/a/55409116/1904943 ) эти имена файлов - все они имеют числовые имена, начиная с 1, в каждом каталоге - и добавив до 5 общих цифр, я должен быть в порядке ,


добавление

Найти общее количество файлов, подкаталогов в каталоге.

$ date; pwd
Tue 14 May 2019 04:08:31 PM PDT
/home/victoria/Mail/2_RESEARCH - NEWS

$ ls | head; echo; ls | tail
Acoustics
Ageing
Ageing - Calorie (Dietary) Restriction
Ageing - Senescence
Agriculture, Aquaculture, Fisheries
Ancient DNA; Ancient Protein
Anthropology, Archaeology
Ants
Archaeology
ARO-Relevant Literature, News

Transcriptome - CAGE
Transcriptome - FISSEQ
Transcriptome - RNA-seq
Translational Science, Medicine
Transposons
USACEHR-Relevant Literature
Vaccines
Vision, Eyes, Sight
Wasps
Women in Science, Medicine

$ find . -type f | wc -l
70214    ## files

$ find . -type d | wc -l
417      ## subdirectories
Виктория Стюарт
источник
0

Здесь много правильных ответов. Вот еще один!

find . -type f | sort | uniq -w 10 -c

где .папка для поиска и 10количество символов, по которым нужно сгруппировать каталог.

рыба фугу
источник
-1

найти -тип f | туалет

ИЛИ (если каталог является текущим каталогом)

найти . тип F | туалет

user128364
источник
Это дублирует, по крайней мере, еще один ответ на этот же вопрос.
Кусалананда
-1

Это будет работать совершенно нормально. Просто коротко. Если вы хотите посчитать количество файлов, присутствующих в папке.

ls | wc -l
Сахил Нагпал
источник
3
Прежде всего, это не отвечает на вопрос. Речь идет о рекурсивном подсчете файлов из каталога вперед, а показанная вами команда этого не делает. Более того, с помощью ls вы считаете каталоги и файлы. Кроме того, нет причин отвечать на старый вопрос, если вы не собираетесь добавлять что-то новое и даже не собираетесь читать вопрос правильно. Пожалуйста, воздержитесь от этого.
XFCC
-1

Этот альтернативный подход с фильтрацией по формату подсчитывает все доступные модули ядра grub:

ls -l /boot/grub/*.mod | wc -l
DanielK
источник
-3
ls -l | grep -e -x -e -dr | wc -l 
  1. длинный перечень
  2. фильтровать файлы и каталоги
  3. считать отфильтрованную строку нет
Баран
источник