количество (непустых) строк кода в bash


151

В Bash как подсчитать количество непустых строк кода в проекте?


1
Многие из приведенных ниже решений работают только для одного файла (например foo.c). Любые мысли о количестве строк в проекте (например, много файлов в структуре каталогов, и исключая двоичные файлы)?
— разгадывание головоломок

5
@solvingPuzzles Я думаю, что могу ответить на эту часть. Для любого решения, которое работает с одним файлом, например «cat FILE | sed blah», вы можете работать со многими файлами, заменив «cat FILE» командой, в которой перечислены имена файлов, с которыми нужно работать, например, «find. -Name» * .py '", и отправьте это в" xargs cat ". например, "find. -name '* .py' | xargs cat | sed '/ ^ \ s * $ / d' | wc -l"
— Джонатан Хартли

2
@JonathanHartley @solvingPuzzles также есть подобные программы, slocи clocони здесь для подсчета количества строк кода.
— AsTeR

OP здесь: Когда я впервые задал эту проблему, cloc не очень хорошо справился с Python-кодом. В наше время это здорово.
— Джонатан Хартли,

Cloc также доступен в виде модуля npm и экономит много времени.
— Кришна Ведула

Ответы:


193
cat foo.c | sed '/^\s*$/d' | wc -l

И если вы считаете комментарии пустыми строками:

cat foo.pl | sed '/^\s*#/d;/^\s*$/d' | wc -l

Хотя это зависит от языка.


24
Не уверен, почему вы используете кошку там. Используйте foo.c или foo.pl в качестве имени файла для передачи в sed. sed '/ ^ \ s * $ / d' foo.c | wc -l
— Энди Лестер

28
Просто привычка. Я читаю конвейеры слева направо, что означает, что я обычно начинаю с cat, затем action, action, action и т. Д. Очевидно, конечный результат один и тот же.
— Майкл Крамер

32
Чтобы сделать это для всех файлов во всех подпапках и исключить комментарии с помощью «//», расширьте эту команду следующим образом: find. -type f -name '* .c' -exec cat {} \; | sed '/ ^ \ s * # / d; / ^ \ s * $ / d; / ^ \ s * \ / \ // d' | wc -l
— Бенджамин Интал

11
Вы можете читать слева направо без UUOC: < foo.pl sed 'stuff' | wc -l.
— jw013

22
Вообще говоря, UUOC не важен, но удобочитаемость есть.
— andersand

52
#!/bin/bash
find . -path './pma' -prune -o -path './blog' -prune -o -path './punbb' -prune -o -path './js/3rdparty' -prune -o -print | egrep '\.php|\.as|\.sql|\.css|\.js' | grep -v '\.svn' | xargs cat | sed '/^\s*$/d' | wc -l

Выше приведено общее количество строк кода (пустые строки удалены) для проекта (текущая папка и все подпапки рекурсивно).

В приведенных выше "./blog" "./punbb" "./js/3rdparty" и "./pma" находятся папки, которые я в черном списке, так как я не написал в них код. Также .php, .as, .sql, .css, .js являются расширениями просматриваемых файлов. Любые файлы с другим расширением игнорируются.


1
вариант для приложения Rails: найти. -path './log' -prune -o -path './trunk' -prune -o -path './branches' -prune -o -path './vendor' -prune -o -path './tmp '-prune -o -print | egrep '\ .rb | \ .erb | \ .css | \ .js | \ .yml' | grep -v 'svn' | кот xargs | sed '/ ^ \ s * $ / d' | wc -l
— poseid

1
Вам нужно добавить $в grep ( ...\.js$|...), иначе он будет совпадать feature.js.swp.
— Xeoncross

Вы забыли привязку, поэтому она содержит неправильные файлы. И еще более простая версия с привязкой:find . | egrep '.\.c$|.\.h$' | xargs cat | sed '/^\s*$/d' | wc -l
— Mark Jeronimus

36

Если вы хотите использовать что-то кроме сценария оболочки, попробуйте CLOC :

cloc считает пустые строки, строки комментариев и физические строки исходного кода во многих языках программирования. Он полностью написан на Perl без каких-либо зависимостей вне стандартного дистрибутива Perl v5.6 и выше (код из некоторых внешних модулей встроен в cloc) и поэтому довольно переносим.


2
Когда я впервые задал этот вопрос, 'cloc' считал строки документации Python как строки кода, что было неоптимальным ИМХО. Современные версии 'cloc' теперь считают строки документации Python комментариями, которые мне нравятся гораздо больше.
— Джонатан Хартли

Это правильный ответ! Я только что попробовал cloc out, и он хорошо справляется со своей задачей.
— LeeMobile

31

Есть много способов сделать это, используя обычные утилиты оболочки.

Мое решение:

grep -cve '^\s*$' <file>

При этом выполняется поиск строк в <file> не совпадающих (-v) строках, которые соответствуют шаблону (-e) '^ \ s * $', который является началом строки, за которой следуют 0 или более пробельных символов, а затем к концу строки (т. е. нет содержимого, отличного от пробела), и отобразите количество совпадающих строк (-c) вместо самих совпадающих строк.

Преимущество этого метода перед методами, которые включают в себя конвейерную передачу wc, состоит в том, что вы можете указать несколько файлов и получить отдельный счетчик для каждого файла:

$ grep -cve '^\s*$' *.hh

config.hh:36
exceptions.hh:48
layer.hh:52
main.hh:39

2
Спасибо! Между прочим, wc предоставляет счетчик для каждого данного файла плюс итоговое значение.
— Джонатан Хартли

1
Не, если вы в нее ввязываетесь, хотя по стандарту считается только один файл.
— SpoonMeiser

Это лучший ответ на мой взгляд.
— simhumileco

-eне обязательно. Это нормальное позиционное расположение паттерна, и вы не делаете с ним ничего прикольного. Но нет ничего плохого в том, чтобы быть явным, если это твой стиль.
— Джектоз

13

'wc' считает строки, слова, символы, поэтому для подсчета всех строк (включая пустые) используйте:

wc *.py

Чтобы отфильтровать пустые строки, вы можете использовать grep:

grep -v '^\s*$' *.py | wc

«-v» указывает grep выводить все строки, кроме тех, которые соответствуют «^» - начало строки. «\ s *» - ноль или более пробельных символов. «$» - конец строки * .py - мой пример для все файлы, которые вы хотите посчитать (все файлы Python в текущем каталоге), выводятся в канал wc. Пошли.

Я отвечаю на свой (настоящий) вопрос. Не удалось найти запись переполнения стека, покрывающую это.


5
\ W не соответствует пробелу, оно соответствует несловесным символам. Это противоположность \ w, слово символов. \ W Будет соответствовать всему, что не является буквенно-цифровым или подчеркиванием, и, следовательно, не будет делать то, что вы утверждаете здесь. Вы имеете в виду \ s
— SpoonMeiser

9

Эта команда подсчитывает количество непустых строк.
cat fileName | grep -v ^$ | wc -l
grep -v ^ $ функция регулярного выражения игнорирует пустые строки.


Этот ответ является самым простым
— samthebest

2
В catэтой цепочке нет необходимости :grep -v ^$ fileName | wl -l
— Эталиды

7
В этом нет необходимости, wc -lпотому что у grep -c:grep -vc ^$ fileName
— Jacktose


5
cat 'filename' | grep '[^ ]' | wc -l

должен сделать трюк просто отлично


3
Зачем использовать cat и направлять файл в grep, если вы можете передать имя файла в качестве аргумента для grep?
— SpoonMeiser

правда, это просто старый псевдоним, который у меня есть ... он делает то же самое, что и ваше решение, вместо использования обратного
— curtisk

4
awk '/^[[:space:]]*$/ {++x} END {print x}' "$testfile"

1
Я бы проголосовал за это только потому, что я буквально никогда не видел, чтобы кто-то использовал преинкремент в скрипте awk, но, к сожалению, это учитывает только пустые строки. :) Вы имеете в виду awk '!/^[[:space:]]*$/{++x} END{print x}'. Или, если вы действительно ненавидите негативы awk '{y++} /^[[:space:]]*$/{++x} END{print y-x}'
— ,;

4
grep -cvE '(^\s*[/*])|(^\s*$)' foo

-c = count
-v = exclude
-E = extended regex
'(comment lines) OR (empty lines)'
where
^    = beginning of the line
\s   = whitespace
*    = any number of previous characters or none
[/*] = either / or *
|    = OR
$    = end of the line

Я отправляю это, потому что другие варианты дали неправильные ответы для меня. Это работало с моим источником Java, где строки комментариев начинаются с / или * (я использую * в каждой строке в многострочном комментарии).


Это работоспособное решение. Единственное, на что следует обратить внимание: многострочные комментарии не учитываются
— Amol

2

Вот скрипт Bash, который считает строки кода в проекте. Он рекурсивно просматривает исходное дерево и исключает пустые строки и однострочные комментарии, которые используют «//».

# $excluded is a regex for paths to exclude from line counting
excluded="spec\|node_modules\|README\|lib\|docs\|csv\|XLS\|json\|png"

countLines(){
  # $total is the total lines of code counted
  total=0
  # -mindepth exclues the current directory (".")
  for file in `find . -mindepth 1 -name "*.*" |grep -v "$excluded"`; do
    # First sed: only count lines of code that are not commented with //
    # Second sed: don't count blank lines
    # $numLines is the lines of code
    numLines=`cat $file | sed '/\/\//d' | sed '/^\s*$/d' | wc -l`

    # To exclude only blank lines and count comment lines, uncomment this:
    #numLines=`cat $file | sed '/^\s*$/d' | wc -l`

    total=$(($total + $numLines))
    echo "  " $numLines $file
  done
  echo "  " $total in total
}

echo Source code files:
countLines
echo Unit tests:
cd spec
countLines

Вот как выглядит вывод для моего проекта :

Source code files:
   2 ./buildDocs.sh
   24 ./countLines.sh
   15 ./css/dashboard.css
   53 ./data/un_population/provenance/preprocess.js
   19 ./index.html
   5 ./server/server.js
   2 ./server/startServer.sh
   24 ./SpecRunner.html
   34 ./src/computeLayout.js
   60 ./src/configDiff.js
   18 ./src/dashboardMirror.js
   37 ./src/dashboardScaffold.js
   14 ./src/data.js
   68 ./src/dummyVis.js
   27 ./src/layout.js
   28 ./src/links.js
   5 ./src/main.js
   52 ./src/processActions.js
   86 ./src/timeline.js
   73 ./src/udc.js
   18 ./src/wire.js
   664 in total
Unit tests:
   230 ./ComputeLayoutSpec.js
   134 ./ConfigDiffSpec.js
   134 ./ProcessActionsSpec.js
   84 ./UDCSpec.js
   149 ./WireSpec.js
   731 in total

Наслаждайтесь! - Курран


1

Это будет зависеть от количества файлов в вашем проекте. В теории вы могли бы использовать

grep -c '.' <list of files>

Где вы можете заполнить список файлов с помощью утилиты поиска.

grep -c '.' `find -type f`

Даст вам количество строк на файл.


1
, соответствует пробелу. Это решение работает только в том случае, если вы считаете, что строка, содержащая только пробел, является непустой, что технически так, хотя, вероятно, это не то, что вам нужно.
— SpoonMeiser

1

Скрипт для рекурсивного подсчета всех непустых строк с определенным расширением файла в текущем каталоге:

#!/usr/bin/env bash
(
echo 0;
for ext in "$@"; do
    for i in $(find . -name "*$ext"); do
        sed '/^\s*$/d' $i | wc -l ## skip blank lines
        #cat $i | wc -l; ## count all lines
        echo +;
    done
done
echo p q;
) | dc;

Пример использования:

./countlines.sh .py .java .html

Спасибо @Andy Lester (+1 за ваш комментарий) за «непустую» часть рецепта.
— Кит Пинсон

Спасибо также @Michael Cramer (+1 за ваше сообщение) за первоначальную публикацию (чуть более многословного) "непустого" решения.
— Кит Пинсон

1

Если вы хотите получить сумму всех непустых строк для всех файлов с заданным расширением во всем проекте:

while read line
do grep -cve '^\s*$' "$line"
done <  <(find $1 -name "*.$2" -print) | awk '{s+=$1} END {print s}'

Первый аргумент - это базовый каталог проекта, второй - расширение файла. Пример использования:

./scriptname ~/Dropbox/project/src java

Это немного больше, чем коллекция предыдущих решений.


Этот получает награду за наибольшее количество вызовов fork + exec, запуская grep один раз в строке в каждом файле. ;)
— dannysauer

0
grep -v '^\W*$' `find -type f` | grep -c '.' > /path/to/lineCountFile.txt

дает общее количество для всех файлов в текущем каталоге и его подкаталогах.

НТН!


\ W - это несимвольные символы; это не будет соответствовать линии, как ${-[*]} + $@, например. Который, безусловно, действительный код где-то в мире. ;) Вы имеете в виду \ s для космоса.
— dannysauer

0

Это дает количество строк без учета пустых строк:

grep -v ^$ filename wc -l | sed -e 's/ //g' 


-3

Для этого в Linux уже есть программа под названием 'wc'.

Просто

wc -l *.c 

и это дает вам общее количество строк и строк для каждого файла.


3
Привет. «wc» сам по себе не ищет подкаталоги и не отфильтровывает пустые строки, оба явно заданы в вопросе.
— Джонатан Хартли

wcсчитает пустые строки. ОП хочет подсчитать непустые строки. Это правда, что он захочет использоватьwc , но только после того, как он будет отредактирован потоком с помощьюsed
— EhevuTov
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.