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


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.