Підрахунок рядків коду?


24

якщо я хочу порахувати рядки коду, тривіальна річ

cat *.c *.h | wc -l

Але що робити, якщо у мене є кілька підкаталогів?



3
Поза темою: Чому зайве cat? wc -l *.c *.hробить те саме.
— Томас Падрон-Маккарті

5
@ ThomasPadron-Маккарті Ні, це не так. Вам потрібно wc -l *.c *.h | tail -n 1отримати аналогічний вихід.
— Жил "ТАК - перестань бути злим"

2
Зауважте, що деякі (можливо, навіть більшість) сучасних оболонок (Bash v4, Zsh, напевно, більше) забезпечують використання рекурсивно-глобулінг-механізму, використовуючи **, тож ви могли використовувати wc -l **/*.{h,c}чи щось подібне. Зауважте, що в Bash, принаймні, ця опція (називається globstar) вимкнено за замовчуванням. Але також відзначити , що в даному конкретному випадку, clocчи SLOCCountце набагато кращий варіант. (Також ackможе бути кращим findдля легкого пошуку / переліку вихідних файлів.)
— Kyle Strand

5
wc -l рахує рядки, а не рядки коду. 7000 порожніх рядків все ще відображатимуться в wc-l, але не враховуватимуться в метриці коду. (коментарі теж зазвичай не враховуються)
— coteyr

Відповіді:


49

Найпростіший спосіб - використовувати інструмент під назвою cloc. Використовуйте його таким чином:

cloc .

Це воно. :-)


1
-1 тому, що ця програма не має жодного способу розпізнавати рядки коду мовами поза своїм маленьким, нудним мозком. Він знає про Ada і Pascal, C і C ++ та Java, JavaScript та тип "Enterprise", але він відмовляється рахувати SLOC за допомогою простого розширення файлу, і таким чином є абсолютно марним для DSL, або навіть мов, які просто не знають о.
— кіт

21
@cat Ніщо не є ідеальним, і ніщо не може виконати всі ваші минулі та майбутні вимоги.
— Ho1

2
Що ж, мова програмування, яку CLOC відмовляється визнати, справді відповідає всім моїм минулим та майбутнім вимогам :)
— кіт

6
@cat відповідно до документації CLOC, він може читати у файлі визначення мови, тому існує спосіб розпізнати код на мовах, які він не визначив. Плюс це відкритий код, тому ви завжди можете розширити його, щоб покращити його!
— Centimane

39

Напевно, ви повинні використовувати для цього SLOCCount або cloc , вони розроблені спеціально для підрахунку рядків вихідного коду в проекті, незалежно від структури каталогу тощо; або

sloccount .

або

cloc .

створить звіт про весь вихідний код, починаючи з поточного каталогу.

Якщо ви хочете використовувати findі wc, GNU wcмає хороший --files0-fromваріант:

find . -name '*.[ch]' -print0 | wc --files0-from=-

(Дякую SnakeDoc за пропозицію Cloc !)


+1 для простору. Цікаво те, що запущений sloccount /tmp/stackexchange(створений знову 17 травня після моєї останньої перезавантаження) говорить про те, що орієнтовна вартість на розробку знайдених файлів sh, perl, awk тощо тощо становить $ 11,029. і це не включає однолінійки, які ніколи не вносили його у файл сценарію.
— cas

11
Оцінка вартості на основі рядків коду? Що з усіма людьми, зайнятими для переосмислення спагетті на щось, що є реальним?
— Зупиніть шкодити Моніці

@OrangeDog, ви завжди можете спробувати це врахувати у накладних витратах; Перегляньте документацію для пояснення розрахунку (із дуже старими даними про зарплату) та параметрів, які можна налаштувати.
— Стівен Кітт

5
clocтакож добре: github.com/AlDanial/cloc
— SnakeDoc

@StephenKitt> все ж, головне питання - це відлік часу. Під час очищення коду ви часто стикаєтеся з меншою кількістю рядків. Впевнені, що ви можете спробувати помахати накладними, щоб взяти на себе решту коду для обліку видаленого, але я не бачу, як це краще, ніж в першу чергу просто здогадуватися про всю ціну.
— спектри

10

Оскільки wcкоманда може приймати кілька аргументів, ви можете просто передати всі імена файлів, wcвикористовуючи +аргумент -execдії GNU find:

find . -type f -name '*.[ch]' -exec wc -l {} +

Крім того, bashвикористовуючи параметр оболонки, globstarщоб рекурсивно переміщувати каталоги:

shopt -s globstar
wc -l **/*.[ch]

Інші снаряди за замовчуванням проходять рекурсивно (наприклад zsh) або мають подібний варіант, наприклад globstar, принаймні більшість.


1
+1 за те, що мені не потрібно встановлювати нестандартне програмне забезпечення на машину, де у мене немає root
— Bamboomy

5

Ви можете використовувати findразом з xargsі wc:

find . -type f -name '*.h' -o -name '*.c' | xargs wc -l

2
(Що передбачає шляхи до файлів не містять прогалини, символи нового рядка, одинарні лапки, подвійні лапки з зворотної косої межі , хоча він може також вихід кілька. totalЛіній , якщо кілька wcроків в даний час викликаються.)
— Stéphane Chazelas

Можливо, wcпроблему декількох команд можна вирішити, переходячи findдо while read FILENAME; do . . .doneструктури. А всередині циклу час використання wc -l. Решта - це підсумовування загальних рядків у змінну та відображення її.
— Сергій Колодяжний

5

Якщо ви перебуваєте в середовищі, де ви не маєте доступу до clocтощо, я б запропонував

find -name '*.[ch]' -type f -exec cat '{}' + | grep -c '[^[:space:]]'

Виконання: findрекурсивно здійснює пошук усіх регулярних файлів, ім'я яких закінчується на .cабо, .hі працює catна них. Вихід проводиться через grepпідрахунок усіх незаповнених рядків (тих, що містять щонайменше один непромітний символ).


4

Як було зазначено в коментарях, cat file | wc -lце не рівнозначно wc -l fileтому, що перші друкують лише число, тоді як другі друкують номер та ім'я файлу. Так само cat * | wc -lбуде надруковано лише число, тоді як wc -l *буде надруковано рядок інформації для кожного файлу.

В дусі простоти давайте переглянемо запитання, яке насправді задається:

якщо я хочу порахувати рядки коду, тривіальна річ

cat *.c *.h | wc -l

Але що робити, якщо у мене є кілька підкаталогів?

По-перше, ви можете спростити навіть тривіальну команду:

cat *.[ch] | wc -l

І нарешті, еквівалент багатьох підкаталогів:

find . -name '*.[ch]' -exec cat {} + | wc -l

Це, можливо, можна вдосконалити багатьма способами, наприклад, обмеження відповідних файлів лише звичайними файлами (а не каталогами) шляхом додавання -type f—але ця findкоманда є точно рекурсивним еквівалентом cat *.[ch].


3

Зразок з використанням awk:

find . -name '*.[ch]' -exec wc -l {} \; |
  awk '{SUM+=$1}; END { print "Total number of lines: " SUM }'

Використання +замість \;.
— Джонатан Леффлер

@JonathanLeffler Чому?
— Хастур

1
@Hastur: Він працює wc -lдля груп файлів, як і xargsробить, але він обробляє символи непарних кульок (як пробіли) у назвах файлів, не потребуючи ані того, xargsані (нестандартного) -print0та -0параметрів відповідно findта xargsвідповідно. Це незначна оптимізація. Мінусом було б те, що кожне виклик wcбуде виводити підсумковий підрахунок рядків у кінці при наданні декількох файлів - awkсценарій мав би справу з цим. Таким чином, це не слем-данк, але дуже часто, використовуючи +замість \;з findхорошою ідеєю.
— Джонатан Леффлер

@JonathanLeffler Дякую Я згоден. Проте я хвилювався щодо довжини переданого рядка параметра wc. Якщо невідомо апріорі кількість файлів, які будуть знайдені , чи існує ризик перейти цю межу або якимось чином обробляється знахідкою?
— Хастур

2
@Hastur: findгрупує файли в групи з зручним розміром, які не перевищуватимуть обмеження довжини для списку аргументів на платформі, враховуючи середовище (яке виходить із довжини списку аргументів - тому довжина списку аргументів плюс довжина середовища повинна бути меншою, ніж максимальне значення). IOW, findчи правильно працює робота, як xargsце робиться правильно.
— Джонатан Леффлер

1

проста команда:

find . -name '*.[ch]' | xargs wc -l

(Що передбачає шляхи до файлів не містять прогалини, символи нового рядка, одинарні лапки, подвійні лапки з зворотної косої межі , хоча він може також вихід кілька. totalЛіній , якщо кілька wcроків в даний час викликаються.)
— Stéphane Chazelas

0

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

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

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

poly .

-2

find . -name \*.[ch] -print | xargs -n 1 wc -lповинен зробити трюк. Існує кілька можливих варіантів для цього, наприклад, використання -execзамість того, щоб підключити вихід wc.


4
Але find . -name \*.[ch] -printне друкується вміст файлів, лише імена файлів. Тож я підраховую кількість файлів замість цього, чи не так? Чи потрібні `xargs '?
— Ніклас

@ Programmer400 так, вам знадобиться xargs, і ви також повинні стежити за кількома wcвикликами, якщо у вас багато файлів; вам потрібно буде шукати всі totalрядки та підсумовувати їх.
— Стівен Кітт

Якщо ви просто хочете загальну кількість ліній, вам знадобиться зробити цеfind . -name \*.[ch] -print0 | xargs -0 cat | wc -l
— пухнастий

Зауважте, що цей ( find . -name \*.[ch] -print | wc -l) рахує кількість файлів (якщо ім'я файлу не містить новий рядок - але це дуже незвично) - він не враховує кількість рядків у файлах.
— Джонатан Леффлер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.