Як підрахувати всі рядки коду в каталозі рекурсивно?


1623

У нас є програма PHP і хочемо порахувати всі рядки коду під певним каталогом та його підкаталогами. Нам не потрібно ігнорувати коментарі, оскільки ми просто намагаємось отримати грубу думку.

wc -l *.php 

Ця команда чудово працює в заданому каталозі, але ігнорує підкаталоги. Я думав, що це може спрацювати, але повертається 74, що точно не так ...

find . -name '*.php' | wc -l

Який правильний синтаксис подавати у всі файли?

Відповіді:


2649

Спробуйте:

find . -name '*.php' | xargs wc -l

Також може допомогти інструмент SLOCCount .

Це дасть точний підрахунок рядків коду для будь-якої ієрархії, на яку ви вказуєте, а також деякі додаткові статистичні дані.

Відсортований вихід:

find . -name '*.php' | xargs wc -l | sort -nr


31
cloc.sourceforge.net, можливо, варто розглядати як альтернативу sloccount (більше мов, але менше інформації)
AsTeR

31
з включенням файлів також:find . -name '*.php' -o -name '*.inc' | xargs wc -l
rymo

52
Це надрукує більше ніж одне число, коли буде багато файлів (оскільки wcвони будуть запущені кілька разів. Також не обробляються багато спеціальних імен файлів.
l0b0,

42
@idober:find . -name "*.php" -not -path "./tests*" | xargs wc -l
endre

19
Якщо ім'я каталогу містить пробіли ... вищезгадана команда не працює !!
nitish712

474

Для ще однієї вкладиші:

( find ./ -name '*.php' -print0 | xargs -0 cat ) | wc -l

працює над іменами з пробілами, виводить лише одне число.


1
+1 ditto ... шукали назавжди ... всі інші команди "find" повернули лише # фактичні файли .... тут -print0 речі отримали для мене фактичну кількість рядків !!! Дякую!
Ронадог

3
@ TorbenGundtofte-Bruun - див man find. .. print0 з xargs -0 дозволяє оперувати файлами, які мають пробіли або інші дивні символи на їх ім'я
Shizzmo

2
@ TorbenGundtofte-Bruun - також -0 у xargs відповідає print0, це своєрідне кодування / декодування для обробки пробілів.
Трістан Рейд

7
Якщо вам потрібно більше одного фільтра імен, я виявив, що (принаймні, з MSYSGit версією пошуку) вам потрібні додаткові парони: ( find . \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 cat ) | wc -l
Zrax,

1
@DesignbyAdrian: Журнал допомагає відновити аварії, а не швидкість. Цілком ймовірно, ви бачите хороші показники через кешування або дуже швидкий жорсткий диск.
jmh

398

Якщо ви використовуєте пристойно недавню версію Bash (або ZSH), це набагато простіше:

wc -l **/*.php

У оболонці Bash для цього потрібна globstarопція, інакше **глобальний оператор не є рекурсивним. Щоб увімкнути це налаштування, виберіть

shopt -s globstar

Щоб зробити це постійним, додайте його в один з файлів ініціалізації ( ~/.bashrc, і ~/.bash_profileт.д.).


7
Я підтримую це для простоти, однак я просто хочу зазначити, що не видається, що рекурсивно шукати каталоги, він лише перевіряє підкаталоги поточного каталогу. Це на SL6.3.
Годрік Провид

7
Це залежить від вашої оболонки та параметрів, які ви встановили. Bash потрібно globstarвстановити, щоб це працювало.
Майкл Дикий

2
@PeterSenna, з поточним архівом ядра 3.9.8, команда wc -l **/*.[ch]знаходить загалом 15195373 рядків. Не впевнений, чи вважаєте ви це "дуже низьким значенням". Знову ж таки, вам потрібно переконатися, що ви globstarвключили в Bash. Ви можете перевірити shopt globstar. Щоб увімкнути це явно, зробіть shopt -s globstar.
Майкл Уайлд

5
@MichaelWild Це хороше рішення, але воно все одно переповниться, ARG_MAXякщо у вас є велика кількість .phpфайлів, оскільки wcвін не вбудований.
Відновіть Моніку. Будь ласка,

1
@AlbertSamuel Ні, вам потрібно буде порівняти список файлів, створених обома методами. Мій метод має проблему не працювати для великої кількості файлів, про що згадує @BroSlow. Прийнята відповідь буде невдалою, якщо шляхи, створені за допомогою findпробілів Це може бути виправлено за допомогою print0і --nullз findі xargsвикликів, відповідно.
Майкл Уайлд

363

Ви можете використовувати clocутиліту, яка побудована саме для цієї мети. Він повідомляє про кількість рядків на кожній мові, а також про кількість коментарів тощо. CLOC доступний для Linux, Mac та Windows.

Приклад використання та виведення:

$ cloc --exclude-lang=DTD,Lua,make,Python .
    2570 text files.
    2200 unique files.                                          
    8654 files ignored.

http://cloc.sourceforge.net v 1.53  T=8.0 s (202.4 files/s, 99198.6 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Javascript                    1506          77848         212000         366495
CSS                             56           9671          20147          87695
HTML                            51           1409            151           7480
XML                              6           3088           1383           6222
-------------------------------------------------------------------------------
SUM:                          1619          92016         233681         467892
-------------------------------------------------------------------------------

4
Це прекрасний інструмент, який добре працює і швидко дає корисну статистику в кінці. Любіть це.
Роб Форест

4
Зауважте, що ви можете запускати команди Unix у Windows за допомогою cygwin (або інших подібних портів / середовищ). Для мене такий доступ дуже надзвичайно корисний - це необхідність. Командний рядок Unix є магічним. Особливо мені подобаються perl та регулярні вирази.
Кертіс Яллоп

CLOC та SLOCCount прекрасно працюють у середині 2015 року. Зауважте, їх кількість близька, але не зовсім однакова для проекту 127k Java Android. Також зауважте, що еквівалент iOS мав 2x LoC; тож показник "вартість" у SLOCCount може бути відключений (а може бути, iOS Dev зробить 2 рази те, що робить Android Dev. :-)
maxweber

2
Чи можете ви відредагувати початок цього питання, щоб зрозуміти, що clocце кросплатформна платформа, оскільки це лише сценарій Perl?
Кайл Странд

Просто ідеально, добре працює і в башті Windows.
yurisnm

100

У системах, схожих на UNIX, існує інструмент, clocякий називається статистикою коду.

Я наткнувся на випадковий каталог у нашій кодовій базі:

      59 text files.
      56 unique files.                              
       5 files ignored.

http://cloc.sourceforge.net v 1.53  T=0.5 s (108.0 files/s, 50180.0 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C                               36           3060           1431          16359
C/C++ Header                    16            689            393           3032
make                             1             17              9             54
Teamcenter def                   1             10              0             36
-------------------------------------------------------------------------------
SUM:                            54           3776           1833          19481
-------------------------------------------------------------------------------

2
@moose технічно simtao згадував це спеціально як рішення для користувачів Windows, зовсім не згадуючи Linux або Unix.
Тім Сегейн

5
@moose Таблиця була відредагована у його відповіді набагато пізніше моєї відповіді, тепер вони дійсно схожі.
Кальмарій

Мені це подобається. cloc дійсно акуратний. Але що означає це ім’я?
Manoel Vilela

Це зараз і в Windows! Якщо припустити, що у вас шоколадний :choco install cloc
icc97

35

Ви не вказали, скільки файлів є або бажаний вихід. Це те, що ви шукаєте:

find . -name '*.php' | xargs wc -l

2
Це буде спрацьовувати, якщо файлів не надто багато: якщо файлів багато, у результаті ви отримаєте кілька рядків (xargs розділить список файлів на декілька під-списків)
Pascal MARTIN

ах, так. Тому я сказав, що він не уточнив, скільки файлів є. Мою версію легше запам’ятати, але версія Шіна краще, якщо у вас є кілька файлів. Я голосую за це.
Paweł Polewicz

Мені потрібно було пристосувати це для використання у функції, де одиничні лапки є занадто обмежувальними: go () { mkdir /tmp/go; [[ -f ./"$1" ]] && mv ./"$1" /tmp/go; (find ./ -type f -name "$*" -print0 | xargs -0 cat ) | wc -l; wc -l /tmp/go/*; mv /tmp/go/* . } результати були близькі до slocount для *.py, але він не знав *.js, *.html.
jalanb

31

Ще одна варіація :)

$ find . -name '*.php' | xargs cat | wc -l

Редагувати: це дасть загальну суму замість файлу за файлом.

Edit2: додайте .після, findщоб він працював


обидві відповіді підсумовують рядки.
josh123a123

Принаймні, у cygwin, я мав кращі результати з:$ find -name \*\.php -print0 | xargs -0 cat | wc -l
Мартін Хаберлі

для Дарвіна це просто дає велику суму: find . -name '*.php' | xargs cat | wc -l... тоді як це дає файли за файлом та велику суму:find . -name '*.php' | xargs wc -l
OsamaBinLogin

30

Дивно, але немає відповіді на основі знахідки -execта awk. Ось і ми:

find . -type f -exec wc -l {} \; | awk '{ SUM += $0} END { print SUM }'

Цей фрагмент знаходить для всіх файлів ( -type f). Щоб знайти розширення файлу, використовуйте -name:

find . -name '*.py' -exec wc -l '{}' \; | awk '{ SUM += $0; } END { print SUM; }'

2
Функціонально це працює чудово, але у великих лістингах (джерело Linux) це дуже повільно, оскільки він запускає процес wc для кожного файлу замість 1 wc процесу для всіх файлів. Я приуротив його до 31 секунди, використовуючи цей метод, порівняно з 1,5 секунди використання find . -name '*.c' -print0 |xargs -0 wc -l. Однак, цей більш швидкий метод (принаймні, на OS X) закінчується друком "всього" кілька разів, тому потрібна додаткова фільтрація, щоб отримати належну загальну суму (я розмістив деталі у своїй відповіді).
Дуг Річардсон

Це має перевагу роботи над необмеженою кількістю файлів. Молодці!
ekscrypto

1
Це набагато краще рішення, коли ви працюєте з великою кількістю ГБ та файлів. робити це wcна формі a catповільно, оскільки система спочатку повинна обробити всі ГБ, щоб почати підрахунок рядків (протестовано на 200 Гб jsons, 12k файлів). Робити wcспочатку, то підрахунок результату набагато швидший
ulkas

1
@DougRichardson, ви можете замість цього розглянути: find . -type f -exec wc -l {} \+або find . -name '*.py' -type f -exec wc -l {} \+ який виводить загальну суму в кінці виводу. Якщо все, що вас цікавить, це загальна сума, то ви можете піти трохи далі і скористатися tail: find . -type f -exec wc -l {} \+ | tail -1абоfind . -name '*.py' -type f -exec wc -l {} \+ | tail -1
JamieJag

25

Більш поширений і простий, як на мене, припустимо, вам потрібно рахувати файли з різними розширеннями імен (скажімо, також уродженими)

wc $(find . -type f | egrep "\.(h|c|cpp|php|cc)" )

Дякую за відгук, я його виправив.


6
це не зовсім те, що ви думаєте. знайти. -name ' . [am]' є тотожним для знаходження. -name ' . [a | m]' обидва знайдуть усі файли, які закінчуються .m або .a
Omry Yadan

1
але другий також знайде файли, що закінчуються , якщо хто-небудь. Отже, [h | c | cpp | php | cc] в кінцевому підсумку є тим самим, що і [hcp |].
OsamaBinLogin

зворотні лапки є застарілими, вважають за краще$()
Сендберг

Це працює під Cygwin. Звичайно, накопичувач "C: \" повинен дотримуватися конвенції cygwin, як, наприклад,: wc $ (find / cygdrive / c // SomeWindowsFolderj / -type f | egrep "\. (H | c | cpp | php | сс) ")
Крістіан

21

POSIX

На відміну від більшості інших відповідей тут, вони працюють у будь-якій системі POSIX, для будь-якої кількості файлів та будь-яких імен файлів (крім випадків, де зазначено).


Рядки у кожному файлі:

find . -name '*.php' -type f -exec wc -l {} \;
# faster, but includes total at end if there are multiple files
find . -name '*.php' -type f -exec wc -l {} +

Рядки у кожному файлі, відсортовані по шляху файлу

find . -name '*.php' -type f | sort | xargs -L1 wc -l
# for files with spaces or newlines, use the non-standard sort -z
find . -name '*.php' -type f -print0 | sort -z | xargs -0 -L1 wc -l

Рядки у кожному файлі, відсортовані за кількістю рядків, у зменшенні

find . -name '*.php' -type f -exec wc -l {} \; | sort -nr
# faster, but includes total at end if there are multiple files
find . -name '*.php' -type f -exec wc -l {} + | sort -nr

Усього рядків у всіх файлах

find . -name '*.php' -type f -exec cat {} + | wc -l

19

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


Що стосується Windows, LocMetrics виконує завдання
Каміль

15

Те, що вам потрібно, це простий forцикл:

total_count=0
for file in $(find . -name *.php -print)
do
    count=$(wc -l $file)
    let total_count+=count
done
echo "$total_count"

3
Це не надмірне вбивство порівняно з відповідями, які підказують xargs?
Натан Фелман

5
Ні, Натане. Відповіді xargs не обов'язково друкують кількість як єдине число. Це може просто надрукувати купу підсумків.
Роб Кеннеді

3
що буде робити ця програма, якщо імена файлів містять пробіли? Що з новинками? ;-)
Paweł Polewicz

38
Якщо назви ваших файлів містять нові рядки, я б сказав, що у вас є більші проблеми.
Kzqai

2
@ennuikiller Кількість питань, пов’язаних із цим, в першу чергу воно порушиться на файли з пробілами. Встановлення IFS=$'\n'перед циклом принаймні виправить це для всіх, крім файлів з новими рядками в їх іменах. По-друге, ви не цитуєте '*.php', тому воно розшириться оболонкою, а не find, і ergo насправді не знайде жодного з файлів php у підкаталогах. Також це -printє зайвим, оскільки мається на увазі за відсутності інших дій.
Відновіть Моніку. Будь ласка,


11

Простий, який буде швидким, використовуватиме всю потужність пошуку / фільтрації find, не вийде з ладу, коли забагато файлів (аргументи числа переповнюються), добре працювати з файлами із забавними символами на їх ім'я, не використовуючи xargs, не запустить безцільно велику кількість зовнішніх команд (завдяки +за find«и -exec). Ось вам:

find . -name '*.php' -type f -exec cat -- {} + | wc -l

2
Я вже збирався опублікувати варіант цього варіанта (а \;замість того, +як я цього не знав), ця відповідь повинна бути правильною відповіддю.
Марк К Коуан

7

Я знаю, що питання позначене як , але здається, що проблема, яку ви намагаєтеся вирішити, також пов'язана з PHP.

Себастьян Бергманн написав інструмент під назвою PHPLOC, який робить те, що ви хочете, а крім того, дає вам огляд складності проекту. Це приклад його звіту:

Size
  Lines of Code (LOC)                            29047
  Comment Lines of Code (CLOC)                   14022 (48.27%)
  Non-Comment Lines of Code (NCLOC)              15025 (51.73%)
  Logical Lines of Code (LLOC)                    3484 (11.99%)
    Classes                                       3314 (95.12%)
      Average Class Length                          29
      Average Method Length                          4
    Functions                                      153 (4.39%)
      Average Function Length                        1
    Not in classes or functions                     17 (0.49%)

Complexity
  Cyclomatic Complexity / LLOC                    0.51
  Cyclomatic Complexity / Number of Methods       3.37

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


7

Здогадуючись, ніхто не побачить цього закопаного ззаду ... Але жодна відповідь досі не потрапляє на проблему назви файлів з пробілами. Крім того, все, що використовується xargs, може зазнати збою, якщо загальна довжина шляхів у дереві перевищує обмеження розміру середовища оболонки (за замовчуванням до декількох мегабайт в Linux). Ось одна, яка виправляє ці проблеми досить прямо. Підрозділ піклується про файли з пробілами. awkСтановить потік окремих файлів wcвиходів, тому ніколи не повинен бігти з космосу. Він також обмежує execлише файли (пропуск каталогів):

find . -type f -name '*.php' -exec bash -c 'wc -l "$0"' {} \; | awk '{s+=$1} END {print s}' 

6

Туалет -L? краще використовувати GREP -C ^

wc -l? Неправильно! Команда wc рахує нові коди рядків, а не рядки! Якщо останній рядок у файлі не закінчується новим кодом рядка, це не враховується!

якщо ви все ще хочете рахувати рядки, використовуйте grep -c ^ , повний приклад:

#this example prints line count for all found files
total=0
find /path -type f -name "*.php" | while read FILE; do
     #you see use grep instead wc ! for properly counting
     count=$(grep -c ^ < "$FILE")
     echo "$FILE has $count lines"
     let total=total+count #in bash, you can convert this for another shell
done
echo TOTAL LINES COUNTED:  $total

нарешті, слідкуйте за пасткою wc -l (рахується входить, а не рядки !!!)


Будь ласка, прочитайте визначення рядка POSIX . Коли grep -c ^ви рахуєте кількість неповних рядків , і такі неповні рядки не можуть відображатися у текстовому файлі .
gniourf_gniourf

2
Я це знаю. Насправді лише останній рядок може бути неповним, оскільки він не має EOL. Ідея підраховує всі рядки, включаючи неповний. Це дуже часта помилка, рахуючи лише повні рядки. після підрахунку ми думаємо "чому я пропустив останній рядок ???". Це відповідь, чому, і рецепт, як це зробити правильно.
Znik

Або, якщо ви хочете один лайнер: find -type f -name '*.php' -print0 | xargs -0 grep -ch ^ | paste -sd+ - | bc Дивіться тут альтернативи bc: stackoverflow.com/q/926069/2400328
techniao

5

З глобусом zsh це дуже просто:

wc -l ./**/*.php

Якщо ви використовуєте bash, вам просто потрібно оновити. Немає абсолютно ніяких причин використовувати bash.


4

дуже просто

find /path -type f -name "*.php" | while read FILE
do
    count=$(wc -l < $FILE)
    echo "$FILE has $count lines"
done

1
не вдасться, якщо в одній із назв файлів є пробіл чи новий рядок
Paweł Polewicz

4

Якщо ви хочете, щоб ваші результати були відсортовані за кількістю рядків, ви можете просто додати | sortабо | sort -r( -rу порядку зменшення) до першої відповіді, наприклад так:

find . -name '*.php' | xargs wc -l | sort -r

1
Оскільки вихід xargs wc -lє числовим, насправді потрібно використовувати sort -nабо sort -nr.
Дастін Інграм

4

Для Windows простий та швидкий інструмент - LocMetrics .


Навряд чи OP є в Windows, якщо вони використовують bash.

1
Заголовок та опис @VanessaMcHale однозначно не вимагають рішення лише для Unix. Тож рішення на базі Windows прийнятні. Також Google вказав мені на цю сторінку, коли я шукав подібне рішення.
walv

Цей коментар мені допоміг. Я спробував це, і це працює добре.
Аллан Ф

4

Щось інше:

wc -l `tree -if --noreport | grep -e'\.php$'`

Це працює відмінно, але ви повинні мати принаймні один *.phpфайл в цій папці або однієї з вкладених папок, або wcкіоски


може також переповнити ARG_MAX
Марк К

4

Якщо ви працюєте в Linux (і я вважаю, що ви є), я рекомендую мій інструмент поліглот . Це різко швидше, ніж будь-який sloccountабо, clocі є більш характерним, ніж sloccount.

Ви можете викликати це

poly .

або

poly

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


4

Інструмент Tokei відображає статистику щодо коду в каталозі. Tokei покаже кількість файлів, загальну кількість рядків у цих файлах та код, коментарі та пробіли, згруповані за мовою. Tokei також доступний на Mac, Linux та Windows.

Приклад виходу Tokei такий:

$ tokei
-------------------------------------------------------------------------------
 Language            Files        Lines         Code     Comments       Blanks
-------------------------------------------------------------------------------
 CSS                     2           12           12            0            0
 JavaScript              1          435          404            0           31
 JSON                    3          178          178            0            0
 Markdown                1            9            9            0            0
 Rust                   10          408          259           84           65
 TOML                    3           69           41           17           11
 YAML                    1           30           25            0            5
-------------------------------------------------------------------------------
 Total                  21         1141          928          101          112
-------------------------------------------------------------------------------

Tokei можна встановити, дотримуючись інструкцій у файлі README у сховищі .


1
Це має бути прийнята відповідь
Ілля

3

Якщо вам потрібна лише загальна кількість рядків, скажімо, у ваших PHP-файлах, ви можете використовувати дуже просту команду однієї лінії навіть під Windows, якщо у вас встановлений GnuWin32. Подобається це:

cat `/gnuwin32/bin/find.exe . -name *.php` | wc -l

Вам потрібно вказати, де саме знаходиться find.exe, інакше буде виконано надане Windows FIND.EXE (зі старих команд, схожих на DOS), оскільки це, ймовірно, перед GnuWin32 в середовищі PATH, і має різні параметри та результати.

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


У наведеному вище прикладі я використовую bash для windows замість cmd.exe, тому є косої риски вперед / ", а не назад".
Невен Боянов

3

Спочатку видайте найдовші файли (тобто, можливо, ці довгі файли потребують певного рефакторингу любові?) Та виключаючи деякі каталоги постачальників:

 find . -name '*.php' | xargs wc -l | sort -nr | egrep -v "libs|tmp|tests|vendor" | less

3

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

wc -l `find . -name "*.php"`

Або в сучасному синтаксисі:

wc -l $(find . -name "*.php")

Працює до тих пір, поки в жодному із назв каталогів чи ім’ях файлів немає пробілів. І поки у вас немає десятків тисяч файлів (сучасні оболонки підтримують дійсно довгі командні рядки). У вашому проекті 74 файли, тож у вас є багато місця для зростання.


Мені подобається цей! Якщо ви перебуваєте в гібридному середовищі C / C ++:wc -l `find . -type f \( -name "*.cpp" -o -name "*.c" -o -name "*.h" \) -print`
Брем

був здивований, що це не найкраща відповідь
ms4720

3

Вам не потрібні всі ці складні і важкі для запам'ятовування команди. Вам просто потрібен інструмент, який називається лічильник ліній .

Швидкий огляд

Ось як ви отримуєте інструмент

$ pip install line-counter

Використовуйте lineкоманду, щоб отримати кількість файлів та кількість рядків у поточному каталозі (рекурсивно)

$ line
Search in /Users/Morgan/Documents/Example/
file count: 4
line count: 839

Якщо ви хочете більше деталей, просто використовуйте line -d.

$ line -d
Search in /Users/Morgan/Documents/Example/
Dir A/file C.c                                             72
Dir A/file D.py                                           268
file A.py                                                 467
file B.c                                                   32
file count: 4
line count: 839

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

Більш детальний опис та використання тут: https://github.com/MorganZhang100/line-counter


3

Якщо файлів занадто багато, краще просто знайти загальну кількість рядків.

find . -name '*.php' | xargs wc -l | grep -i ' total' | awk '{print $1}'

2

Принаймні, в OS X команди find + xarg + wc, перелічені в деяких інших відповідях, друкують "усього" декілька разів у великих списках, і не вказано повного загального числа. Я зміг отримати єдине загальне для файлів .c за допомогою наступної команди:

find . -name '*.c' -print0 |xargs -0 wc -l|grep -v total|awk '{ sum += $1; } END { print "SUM: " sum; }'

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