Рекурсивний підрахунок файлів у каталозі Linux


728

Як я можу рекурсивно рахувати файли в каталозі Linux?

Я знайшов це:

find DIR_NAME -type f ¦ wc -l

Але коли я запускаю це, то повертається наступна помилка.

find: шляхи повинні передувати виразу: ¦


64
Ви плутаєте зламану планку ¦(ASCII 166) з вертикальною смугою |(ASCII 124), яка використовується для трубопроводу UNIX .
Skippy le Grand Gourou

7
@SkippyleGrandGourou Хіба це не називається трубою?
DaveStephens

27
@DaveStephens Так, це також називається. Її також називають штриховим штрихом, верти-баром, vbar, палицею, вертикальною лінією, вертикальною косою рисою, бруском, обеліском, глидусом.
emlai

64
@zenith Я просто називаю це Боб.
Крістофер

15
У RFC20 це називається "вертикальна лінія". "Труба" - це ім'я оператора оболонки, а не назва символу. Так само, як *і символ зірочки ASCII, але "раз" у деяких інших контекстах.
струнка

Відповіді:


1325

Це має працювати:

find DIR_NAME -type f | wc -l

Пояснення:

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

Примітки:

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

Пояснення, чому ваш приклад не працює:

У команді, яку ви показали, ви не використовуєте "Трубу" ( |) для виведення з'єднання двох команд, але зламану смугу ( ¦), яку оболонка не визнає як команду чи щось подібне. Ось чому ви отримуєте це повідомлення про помилку.


26
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 Ваш коментар стосується майже кожної відповіді тут.
трійка

69

Якщо ви хочете розбити кількість файлів у кожному dir під вашим поточним dir:

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

функція count {for i в $ (знайдіть -maxdepth 1 -тип d); do file_count = $ (знайти $ i -тип f | wc -l); echo "$ file_count: $ i"; зроблено}; підрахунок | сортувати -n -r
Шнеем

Нарешті, це те, що мені було потрібно. У моїх папках є тисячі файлів, тому друкувати їх на дереві чи будь-що інше - це не варіант
lesolorzanov

Це включає ../ і, здається, не йде вперед - це означає, що це не регресивно.
Даніель Лефевр

50

Можна використовувати

$ tree

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

$ sudo apt-get install tree

(на машині Debian / Mint / Ubuntu Linux).

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

Приховані файли можна також включити, надавши -aопцію.


4
Це насправді найпростіший спосіб переглянути кількість каталогів та файлів.
Лорем Іпсум Долор

11
На сторінці man: Дерево за замовчуванням не друкує приховані файли . Ви повинні надати -aможливість включити їх.
eee

3
Щоб встановити це на macOS, використовуйте brewта запустіть brew install tree, бажано після запуску brew update.
Ашиш Ахуджа

4
Він також друкує всі імена файлів, тому це буде повільно, якщо у вас буде багато файлів.
Франк Дернонкур

2
Нічого собі, дуже приємний інструмент, він може друкувати кольорові папки, список лише папок, виводити як JSON. Він може перелічити 34k папки та 51k файли за дуже кілька секунд. Оле!
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

Спасибі @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
psmith

20

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

find DIR_NAME -type f -printf "." | wc -c

1
Схоже, це єдине рішення, яке обробляє файли з новими рядками у своїх іменах. Отримано.
codeforester

2
hihi :) Я люблю нові рядки у назви файлів. Це робить їх просто читабельнішими.
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"для друку імені каталогу.
трійчатка

10

Якщо ви хочете знати, скільки файлів і підкаталогів існує з поточного робочого каталогу, ви можете скористатися цим одноклассником

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

Це буде працювати в ароматі GNU і просто опустити команду -e для команди BSD для Linux (наприклад, OSX).


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`, як у попередньому коментарі) для нецитованого імені каталогу торгує однією проблемою для іншої.
тріплей

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

Як мінімум гну 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 це сподобалось. Я маю багато файлів у папці, а панель прогресу - це економія життя. Дякую, що поділились!
Geek


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повинен виконувати statсистемний виклик кожного файлу, щоб прочитати його розмір, mtime та інші властивості, що повільно. У великих каталогах (100 000+ файлів) запуск ls -lможе зайняти кілька хвилин. Тому для підрахунку лише файлів завжди використовуйте ls -1 | wc -l.
Marki555

A 486SX25, приємно
cam8001

ls -1все ще може бути повільним у великих каталогах, оскільки він має сортувати файли. Просто printf '%s\n' *робиться те ж саме, і уникає зовнішнього lsвиклику (що завгодно проблематично ), але найефективнішим солютоном є використання команди, яка не виконує сортування, наприклад find. (Глобальний вихід відсортований за оболонкою.)
tripleee

4

Якщо вам потрібно підрахувати певний тип файлу рекурсивно , ви можете зробити:

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

-l полягає лише у відображенні кількості рядків у висновку.


Розширення є частиною назви файла і може не представляти файл TYPE
Waxhead

4

З баш:

Створіть масив записів за допомогою () та отримайте кількість за допомогою #.

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

Гаразд, що рекурсивно не рахує файли, але я хотів спочатку показати простий варіант. Загальний випадок використання може бути для створення резервних копій файлів, що перевертаються. Це створить logfile.1, logfile.2, logfile.3 і т.д.

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

Рекурсивна кількість з globstarвключеним bash 4+ (як згадує @tripleee)

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

Щоб отримати кількість файлів рекурсивно, ми все ще можемо використовувати пошук таким же чином.

FILES=(`find . -type f`); echo ${#FILES[@]}

Сучасні оболонки підтримують **/*рекурсивне перерахування. Це все ще менш ефективно, ніж findу великих каталогах, оскільки оболонка повинна сортувати файли у кожному каталозі.
трійчатка

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

Додаток: Я хочу знайти максимальну кількість файлів серед кількох сотень каталогів (вся глибина = 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

1

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

Це може бути на порядок швидше , ніж lsабо findпідходи , засновані, але YMMV.


0

Тут є багато правильних відповідей. Ось ще!

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

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


-1

знайти -тип f | wc -l

АБО (якщо каталог - поточний каталог)

знайти. -типу f | wc -l


Це повторює щонайменше ще одну відповідь на це ж запитання.
Кусалаланда

-1

Це буде працювати нормально. Простий короткий. Якщо ви хочете порахувати кількість файлів, присутніх у папці.

ls | wc -l

3
Перш за все, це не дає відповіді на питання. Питання полягає в рекурсивному підрахунку файлів з каталогу вперед, і показана вами команда цього не робить. крім того, з ls ви рахуєте каталоги, а також файли. Також немає підстав відповідати на старе запитання, якщо ви не збираєтесь додавати щось нове і навіть не збираєтесь правильно прочитати питання. Утримайтеся від цього.
XFCC

-1

Цей альтернативний підхід з фільтруванням для формату рахує всі наявні модулі ядра grub:

ls -l /boot/grub/*.mod | wc -l

-3
ls -l | grep -e -x -e -dr | wc -l 
  1. довгий список
  2. фільтрувати файли та бруси
  3. порахуйте відфільтрований рядок немає
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.