рекурсивна статистика типів файлів у каталозі?


65

Я зробив скрап веб-сайту для проекту конверсії. Я хотів би зробити деякі статистичні дані про типи файлів там - наприклад, 400 .htmlфайлів, 100 .gifі т.д. Який простий спосіб це зробити? Це має бути рекурсивним.

Редагувати: зі сценарієм, який розмістив maxschelpzig, у мене виникли деякі проблеми через архітектуру сайту, який я скребкував. Деякі файли мають назву *.php?blah=blah&foo=barз різними аргументами, тому вони вважають їх усіма унікальними. Тому рішення потрібно вважати *.php*всім одного типу, так би мовити.

Відповіді:


96

Ви можете використовувати findі uniqдля цього, наприклад:

$ find . -type f | sed 's/.*\.//' | sort | uniq -c
   16 avi
   29 jpg
  136 mp3
    3 mp4

Пояснення команди

  • find рекурсивно друкує всі імена файлів
  • sed видаляє з кожного імені файлу префікс до розширення файлу
  • uniq передбачає відсортований вхід
    • -c робить підрахунок (як гістограма).

У мене схожий сценарій. Просто і швидко.
Руфо Ель Магуфо

Деякі файли мають назву *.php?blah=blah&foo=barз різними аргументами, тому вони вважають їх усіма унікальними. Як я можу змінити його на пошук *.php*?
користувач394

3
Можна спробувати використати інший вираз sed, наприкладsed 's/^.*\(\.[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]\).*$/\1/'
maxschlepzig

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

1
@ bela83, варіанти чорносливу покладаються на оцінку короткого замикання - таким чином, моя перша версія find -name '.*' -prune -o -type f -printоцінюється як: якщо запис у каталозі збігається, .*то обріжте його, інакше, якщо це файл, тоді його надрукуйте. Оскільки .*також збігається ., тобто CWD, все обрізається, тобто пошук навіть не спускається в перший каталог. Можливо, дворічні версії findповодилися інакше - або це був просто нагляд за мною, тоді. Так чи інакше, find -name '.*' -not -name . -prune -o -type f -printце виправляє.
maxschlepzig

6

З zsh:

print -rl -- **/?*.*(D.:e) | uniq -c |sort -n

Модель **/?*.* відповідає всім файлам , які мають розширення, в поточному каталозі і його підкаталогах рекурсивно. Глоб класифікатор D нехай zshтраверс навіть приховані каталоги і розглянути приховані файли, .вибирає тільки звичайні файли. Модифікатор Історія зберігає тільки розширення файлу. print -rlдрукує одну відповідність на рядок. uniq -cпідраховує послідовно однакові елементи (глобальний результат вже відсортований). Заключний виклик sortсортує розширення за кількістю використання.


5

Цей однолінійний вклад здається досить надійним методом:

find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$/\1/p' | sort | uniq -c

У find . -type f -printf '%f\n'друкує BASENAME кожного звичайного файлу в дереві, без каталогів. Це виключає необхідність турбуватися про каталоги, які можуть бути .в них у вашому sedрегексе.

sed -r -n 's/.+(\..*)$/\1/p'Замінює входить ім'я файлу тільки з його розширенням. Наприклад, .somefile.extстає .ext. Зверніть увагу на початкове .+в регулярному вираженні; це призводить до будь-якої відповідності, яка потребує хоча б одного символу перед розширенням .. Це запобігає тому, щоб назви файлів, як наприклад .gitignore, взагалі не мали імені та розширення '.gitignore', що, мабуть, ви хочете. Якщо немає, то замініть .+з .*.

Решта рядка - з прийнятої відповіді.

Редагувати : Якщо ви хочете добре відсортовану гістограму у форматі діаграми Парето , просто додайте іншу sortдо кінця:

find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$/\1/p' | sort | uniq -c | sort -bn

Приклад виводу зі вбудованого вихідного дерева Linux:

    1 .1992-1997
    1 .1994-2004
    1 .1995-2002
    1 .1996-2002
    1 .ac
    1 .act2000
    1 .AddingFirmware
    1 .AdvancedTopics
    [...]
 1445 .S
 2826 .o
 2919 .cmd
 3531 .txt
19290 .h
23480 .c

1

Я помістив скрипт bash у свою ~/binпапку exhistз таким вмістом:

#!/bin/bash

for d in */ ; do
        echo $d
        find $d -type f | sed -r 's/.*\/([^\/]+)/\1/' | sed 's/^[^\.]*$//' | sed -r 's/.*(\.[^\.]+)$/\1/' | sort | uniq -c | sort -nr
#       files only      | keep filename only          | no ext -> '' ext   | keep part after . (i.e. ext) | count          | sort by count desc
done

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

$ exhist
src/
      7 .java
      1 .txt
target/
     42 .html
     10 .class
      4 .jar
      3 .lst
      2 
      1 .xml
      1 .txt
      1 .properties
      1 .js
      1 .css

PS Обрізання деталі після знака питання має бути простим для виконання іншої команди sed, ймовірно, після останньої (я не пробував): sed 's/\?.*//'

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