Знайдіть каталоги, що містять певну кількість файлів


13

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

find . -filecount +10 # any directory with more than 10 entries
find . -filecount 20 # any directory with exactly 20 entries

Але на жаль, такого варіанту немає.


спробуйте щось на кшталт "ls -al | wc -l | grep"
Ванадіс

Відповіді:


16

Ви можете спробувати це, щоб отримати імена підкаталогу та кількість файлів / каталогів, які вони містять:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \;

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

find . -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \;

Щоб вибрати ті каталоги, які містять рівно 10 файлів:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \; | 
  awk '$NF==10'

10 або більше:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \; | 
 awk '$NF>=10'

10 або менше:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{} '; ls '{}' | wc -l" \; | 
 awk '$NF<=10'

Якщо ви хочете зберегти лише ім'я каталогу (наприклад, ви хочете передати його іншому процесу вниз за течією, як запропоновано @evilsoup), ви можете використовувати це:

find . -maxdepth 1 -type d -exec bash -c "echo -ne '{}\t'; ls '{}' | wc -l" \; | 
 awk -F"\t" '$NF<=10{print $1}'

1
Я думаю, що може бути корисним включити команду awk, щоб відрізати кількість файлів (тобто останній стовпчик, розміщений з пробілом), у випадку, якщо запитуючий прагне вивести вихід на щось інше.
evilsoup

1
@evilsoup гарна ідея, зроблено.
тердон

Підтримка пробілів та спеціальних символів у назвах каталогу; спробуйте скасувати використання одно- та подвійних лапок як таких:find . -type d -exec bash -c 'echo -ne "{} "; ls "{}" | wc -l' \; | awk '$NF<=10'
Håvard Geithus

3

Перелічити безпосередні підкаталоги, що містять саме $NUM файли.

find -maxdepth 2 -mindepth 2 -type f -printf '%h\0' | awk -v num="$NUM" 'BEGIN{RS="\0"} {array[$0]++} END{for (line in array) if (array[line]==num) printf "%s\n", line}'

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

find -maxdepth 2 -mindepth 2 -type f -printf '%h\0' | awk -v num="$NUM" 'BEGIN{RS="\0"} {array[$0]++} END{for (line in array) if (array[line]>num) printf "%s\n", line}'

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

find -maxdepth 2 -mindepth 2 -type f -printf '%h\0' | awk -v num="$NUM" 'BEGIN{RS="\0"} {array[$0]++} END{for (line in array) if (array[line]<num) printf "%s\n", line}'

Елементи закінчуються нульовим символом \0, тому імена файлів, що містять нові рядки або інші види білого простору, будуть інтерпретовані правильно. %hДрукує кожен файл dirname. awkпотім використовує масив, щоб підрахувати, скільки разів він стикається з кожною каталогом, друкуючи його, якщо умови виконані.

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

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


2

Спробуйте це:

[`знайти. | wc -l` -eq 10] && відлуння "Знайдено"

[`знайти. | wc -l` -gt 10] && відлуння "Знайдено"

[`знайти. | wc -l` -lt 10] && відлуння "Знайдено"

У цих прикладах ви можете перевірити, чи CURRENT каталог містить рівно 10, більше 10 та менше 10 файлів / каталогів. Якщо вам потрібно перевірити купу каталогів, просто використовуйте цикл.


Ваше рішення також враховує поточний каталог ( .), який ви можете змінити відповідно.
тердон

Мені подобається порив цієї відповіді (оскільки я обжерливий, щоб робити речі в оболонці), але вам краще використовувати тест wc -l < <(printf %s\\n ./*)або printf %s\\n ./* | wc -lвсередині нього, щоб уникнути зайвого findдзвінка. Це також дозволить уникнути проблеми, яку зазначив @terdon, щодо включення .в результат. Однак це також зіткнеться з проблемою ігнорування файлів, що починаються з а .; Я б вирішив це за допомогою shopt -s dotglob(щоб файли збігалися з глобусами, починаючи з а ., але не .або ..).
evilsoup

@terdon Це не важливо. Це не остаточне рішення, лише приклад, ідея. Ви можете -1 або змінити 10 на 11 у остаточній версії.
вересень

Я знаю, і ідея хороша, тому я зробив свою пропозицію.
тердон

@ terdon. Дякую. Може бути багато різних вимог, наприклад: Підраховуйте лише файли, але не каталоги, посилання чи жорсткі посилання. Зраховувати чи ні файли у підкаталогах. Порахуйте приховані файли (наприклад, .bashrc) ... ... щоб ваш вираз міг бути veeeeery loooong. :)
вересень
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.