Як я можу отримати кількість файлів у каталозі за допомогою командного рядка?


193

У мене є каталог з великою кількістю файлів. Я не бачу lsперемикача для надання рахунку. Чи є якась магія командного рядка, щоб отримати кількість файлів?



tree . | tailабо tree -a . | tailвключати приховані файли / dirs, treeє рекурсивним, якщо саме цього ви хочете.
CodyChan

Відповіді:


239

Використання широкого визначення поняття "файл"

ls | wc -l

(зауважте, що він не враховує приховані файли і припускає, що імена файлів не містять символів нового рядка).

Для включення прихованих файлів (крім .і ..) та уникнення проблем із символами нового рядка канонічним способом є:

find . ! -name . -prune -print | grep -c /

Або рекурсивно:

find .//. ! -name . -print | grep -c //

23
wc- це програма "кількість слів". -lПеремикач змушує його вважати рядки. У цьому випадку це підрахунок рядків у виході з ls. Це завжди те, як мене вчили отримувати підрахунок файлів для заданої директорії.
Сенді

20
будь ласка, додайте до уваги, що lsце робить, ls -1якщо вихід є трубою.
lesmana

6
це не все, що потрапляє в каталог - ви пропустили крапкові файли і збираєте ще пару зайвих рядків. Порожній каталог все одно поверне 1 рядок. А якщо зателефонувати ls -la, ви отримаєте три рядки в каталозі. Ви хочете ls -lA | wc -lпропустити записи .та ..записи. Однак ти все одно будеш поза одним.

1
Порожній каталог повертає 0 для мене
Джеймс Рот,

2
Виправлений підхід, який би не подвоював файли з новими рядками в імені, був би таким: ls -q | wc -l- хоча зауважте, що приховані файли таким підходом все ще не будуть рахуватися, і що каталоги будуть рахуватися.
godlygeek

31

Для вузького визначення файлу:

 find . -maxdepth 1 -type f | wc -l

І, звичайно, можна опустити -maxdepth 1рекурсивно підрахунок файлів (або відрегулювати його на бажану максимальну глибину пошуку).
user7089

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

7
Виправлений підхід, який би не подвоював файли з новими рядками в імені, був би таким:find -maxdepth 1 -type f -printf "\n" | wc -l
godlygeek

+1 Дозволити приховані файли та ігнорувати каталоги
Michael Durrant

14
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS: Примітка ls - <число- одна> | wc - <letter-l>


10
Більшість версій lsроблять -1автоматично, коли вихід на трубу.
Денніс Вільямсон

3
@ Денніс, що цікаво, я не знав, що програма може сказати, що її вихід збирається в дію.
ксенотерацид

1
Я + 'редагував цю версію, оскільки вона більш чітка. Хоча так, так ls використовує -1, якщо це трубопровід (спробуйте: ls | cat), я вважаю синтаксис -1 більш явним.
габе.

3
@xenoterracide: In Bash:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
Денніс Вільямсон

2
У моїх тестах було набагато швидше також забезпечити варіант -f, щоб уникнути сортування імен файлів. На жаль, ви все одно отримаєте неправильну відповідь, якщо ваші імена файлів містять нові рядки.
Семюель Едвін Уорд

10

Напевно, найповніша відповідь, що використовує ls/ wcпара, - це

ls -Aq | wc -l

якщо ви хочете порахувати крапкові файли, і

ls -q | wc -l

інакше.

  • -Aполягає в підрахунку точкових файлів, але опустіть .і ...
  • -qзмусити lsзамінити неграфічні символи, зокрема символи нового рядка, на ?, роблячи вихід 1 рядок для кожного файлу

Для отримання однолінійного виводу з lsтерміналу (тобто, без підключення до нього wc), -1опція повинна бути додана.

(поведінка lsтестованих з coreutils 8.23)


2
Як ви сказали, -1не потрібна. Що стосується того, що "він обробляє нові рядки з назви файлів чітко з консольним виходом" , це пов’язано з -qкомутатором (який слід використовувати замість того, -bщо він є портативним), який "змушує записувати кожен екземпляр символів, що не друкуються, та символів <tab> як символ <question-mark> ('?'). Реалізації можуть надавати цю опцію за замовчуванням, якщо висновок призначений для термінального пристрою. " Так, наприклад, ls -Aq | wc -lпорахувати всі файли / dirs або ls -qp | grep -c /підрахувати лише не приховані dirs тощо ...
don_crissti

Дякуємо за ваш внесок Змінено -bна -q.
Фракс

7

Якщо вам відомо, що поточний каталог містить принаймні один не прихований файл:

set -- *; echo "$#"

Це, очевидно, узагальнюється для будь-якого світу.

У сценарії це іноді невдалий побічний ефект перезапису позиційних параметрів. Ви можете обійти це за допомогою допоміжної оболонки або з функцією (версія Bourne / POSIX), наприклад:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

Альтернативне рішення - це $(ls -d -- * | wc -l). Якщо глобус є *, команду можна скоротити до $(ls | wc -l). Розбір результатів lsзавжди викликає занепокоєння, але тут він повинен працювати до тих пір, поки імена ваших файлів не містять нових рядків, або якщо ви lsїх уникаєте. І $(ls -d -- * 2>/dev/null | wc -l)має перевагу граціозно керувати випадком невідповідного глобу (тобто він повертає 0 у такому випадку, тоді як для цього set *методу потрібно чітко перевірити, чи глобул може бути порожнім).

Якщо імена файлів можуть містити символи нового рядка, слід використовувати альтернативу $(ls -d ./* | grep -c /).

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


1
Ви дійсно хочете створити 13 923 позиційні параметри? І вам слід зробити свою локальну змінну localабо усунути її: eval $1=$#або просто використовувати echo $#та робити number_of_files=$(count_words *).
Денніс Вільямсон

1
@Dennis: частина пункту полягала в тому, щоб уникнути роздрібнення. Я думаю, це не проблема 21 століття. Гаразд, я визнаю, мені більше не байдужі не-POSIX-снаряди, тому я міг уникнути тимчасової змінної.
Жиль

Чому ви відняли його $#(ви цього не робили до редагування)?
Денніс Вільямсон

@Dennis: Я все-таки уникаю вилки (ну, це все-таки має значення на машинах з повільним процесором, таких як маршрутизатори) і передаючи ім'я змінної як $1. Тому я хочу порахувати кількість параметрів, які не є першим параметром. (Я не можу використовувати, shiftтому що мені потрібно зберегти ім'я змінної.) (Гм, тепер, якщо ви запитали про перший рядок ...)
Жил,

@Dennis: придумайте, я можу використати, shiftякщо встигну правильно.
Жил

7

Я вважаю du --inodesкорисним, але я не впевнений, яка версія duцього вимагає. Це має бути значно швидше, ніж використання альтернативних підходів findта wc.

У Ubuntu 17.10 працює наступне:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

Поєднайте з | sort -nrсортування за спаданням за кількістю містять у них вузлів.


5

При використанні пари ls / wc, якщо ми додаємо -U, це буде набагато швидше (не сортувати).

ls -AqU | wc -l

1
-Uє GNU-специфічним.
Стефан Шазелас

4

Після встановлення команди дерева просто введіть:

tree

Якщо ви також хочете приховані файли:

tree -a

Якщо ви використовуєте Debian / Mint / Ubuntu Linux, введіть таку команду, щоб встановити команду дерева:

sudo apt-get install tree

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


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

2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1зробить його нерекурсивним, findза замовчуванням є рекурсивним
  • -type f буде включати лише файли
  • -printf .це милий штрих. він друкує крапку для кожного файлу замість імені файлу, і тепер він може обробляти будь-яке ім'я файлу, а також зберігає дані; нам просто треба порахувати крапки :)
  • | wc -c рахує символів

1

Жодної труби, жодної копії струни, жодної вилки, просто один байдар

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount

1
Дає значення 1, якщо в каталозі немає файлів. Не враховує файли, рахує файли та каталоги.
Стів

1

Ось ще одна техніка за принципом одного розміщеного Жилла :

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

який створює масив з 13 923 елементами (якщо це скільки файлів).


У чому сенс цього cмасиву? word_count() { echo "$#"; }вистачило б Суть рішення @Gilles полягає в збереженні рахунку у поверненій змінній, щоб уникнути необхідності використання підстановки команд (що включає вилку та трубу в оболонках, відмінних від ksh93).
Стефан Шазелас

1
find . -type f -maxdepth 1 |  wc -l 

Тут можна перелічити лише файли в поточному каталозі.


find . -type fзнайде файли в поточному каталозі, а також, рекурсивно, в підкаталогах.
даг

0

Спробуйте це, я сподіваюся, що ця відповідь вам допоможе

echo $((`ls -l | wc -l` -1 ))


0

Удосконалення деяких відповідей, що були раніше, але цього разу явно.

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

Варто помітити використання деяких улюблених команд, таких як tailі cut. Також зауважте, що дерево за замовчуванням недоступне. Команда вгорі спочатку захоплює інформацію про каталог на рівні 1, потім отримує останній рядок, tail -n 1де наша мета, і в кінцевому підсумку, cutщоб взяти третє слово.

Наприклад, розміщення в /:

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

Тоді, а як запитати кількість каталогів?


0

У Linux, щоб зробити команду дуже надійною та обробляти файли, які можуть мати нові рядки у своєму імені, використовуйте це:

find -maxdepth 1 -type f -print0 | tr -cd '\0' | wc -c

Це рятує нас від випробувань синтаксичного аналізу ls.


Пов'язані:


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.