количество (непустых) строк кода в 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) и поэтому довольно переносим.

XSL
источник
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
SpoonMeiser
источник
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
6
cat file.txt | awk 'NF' | wc -l
Jaydillan
источник
люблю простоту этого Ge
Джерард
5
cat 'filename' | grep '[^ ]' | wc -l

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

curtisk
источник
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, где строки комментариев начинаются с / или * (я использую * в каждой строке в многострочном комментарии).

Sami
источник
Это работоспособное решение. Единственное, на что следует обратить внимание: многострочные комментарии не учитываются
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' 
Махеш
источник
0
rgrep . | wc -l

дает количество непустых строк в текущем рабочем каталоге.

Жан-Эммануэль
источник
-3

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

Просто

wc -l *.c 

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

G1i1ch
источник
3
Привет. «wc» сам по себе не ищет подкаталоги и не отфильтровывает пустые строки, оба явно заданы в вопросе.
Джонатан Хартли
wcсчитает пустые строки. ОП хочет подсчитать непустые строки. Это правда, что он захочет использоватьwc , но только после того, как он будет отредактирован потоком с помощьюsed
EhevuTov