Как посчитать все строки кода в каталоге рекурсивно?

1376

У нас есть приложение PHP и мы хотим подсчитать все строки кода под определенным каталогом и его подкаталогами. Нам не нужно игнорировать комментарии, так как мы просто пытаемся получить приблизительную идею.

wc -l *.php 

Эта команда отлично работает в пределах заданного каталога, но игнорирует подкаталоги. Я думал, что это может сработать, но оно возвращается 74, что определенно не так...

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

Какой правильный синтаксис для подачи во всех файлах?

Теги:

42 ответа

2436
Лучший ответ

Попытка:

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

Инструмент SLOCCount также может помочь.

Это даст точные исходные строки кода для любого иерархию, на которую вы указываете ее, а также некоторые дополнительные параметры.

  • 28
    cloc.sourceforge.net, возможно, стоит рассматривать в качестве альтернативы sloccount (больше языков, но меньше информации)
  • 28
    с включаемыми файлами также: find . -name '*.php' -o -name '*.inc' | xargs wc -l
Показать ещё 28 комментариев
399

Для другого однострочного:

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

работает с именами с пробелами, выводит только одно число.

  • 36
    +1 за -print0 / -0
  • 1
    +1 то же самое ... искали вечно ... все остальные команды "find" возвращали только # фактических файлов .... здесь -print0 получил фактическое количество строк для меня !!! Спасибо!
Показать ещё 17 комментариев
381

Если использовать по-прежнему последнюю версию Bash (или ZSH), она намного проще:

wc -l **/*.php

В оболочке Bash для этого требуется установить параметр globstar, в противном случае оператор ** glob не является рекурсивным. Чтобы включить этот параметр, выполните

shopt -s globstar

Чтобы сделать это постоянным, добавьте его в один из файлов инициализации (~/.bashrc, ~/.bash_profile и т.д.).

  • 7
    Я за это проголосую за простоту, однако хочу отметить, что он не ищет рекурсивный поиск в каталогах, он только проверяет подкаталоги текущего каталога. Это на SL6.3.
  • 6
    Это зависит от вашей оболочки и опций, которые вы установили. Bash требует, чтобы globstar был установлен, чтобы это работало.
Показать ещё 6 комментариев
244

Вы можете использовать утилиту 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
-------------------------------------------------------------------------------
  • 2
    Это прекрасный инструмент, который работает хорошо и быстро дает полезную статистику в конце. Любить это.
  • 10
    На Unix работает так же хорошо. И это всего лишь сценарий.
Показать ещё 3 комментария
91

В 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
-------------------------------------------------------------------------------
  • 0
    Это сайт для CLOC: cloc.sourceforge.net
  • 5
    Это тот же ответ, который Симао уже дал в 2011 году.
Показать ещё 5 комментариев
31

Вы не указали, сколько там файлов или какой желаемый результат. Это то, что вы ищите:

find . -name '*.php' | xargs wc -l
  • 2
    Это будет работать, если файлов не слишком много: если файлов много, в результате вы получите несколько строк (xargs разделит список файлов на несколько подсписков).
  • 0
    о да. Вот почему я сказал, что Он не указал, сколько там файлов. Моя версия легче запомнить, но версия Шина лучше, если у вас есть несколько файлов. Я голосую за это.
Показать ещё 2 комментария
20

Еще одна вариация:)

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

Изменить: это даст общую сумму, а не файл за файлом.

  • 2
    Это использует антипаттерн! бесполезное использование кошки!
  • 0
    @ josh123a123, есть лучшее представление, как дать совокупность?
Показать ещё 6 комментариев
19

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
18

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

wc `find . -name '*.[h|c|cpp|php|cc]'`
  • 6
    это не совсем то, что вы думаете. находить . -name ' . [am]' идентичен для поиска. -name ' . [a | m]' оба найдут все файлы, заканчивающиеся на .m или .a
  • 1
    но второй также найдет файлы, оканчивающиеся на. | если есть. Таким образом, [h | c | cpp | php | cc] заканчивается тем же, что и [hcp |].
17

Для подсчета строк кода в каталоге есть небольшой инструмент sloccount. Следует отметить, что он делает больше, чем вы хотите, поскольку он игнорирует пустые строки/комментарии, группирует результаты на язык программирования и вычисляет некоторые статистические данные.

16

Удивительно, но нет ответа на основе поиска -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 }'
  • 1
    Функционально это работает отлично, но для большого списка (источник linux) это действительно медленно, потому что он запускает wc-процесс для каждого файла вместо 1 wc-процесса для всех файлов. Я рассчитал это на 31 секунду, используя этот метод по сравнению с 1,5 секундами, используя find . -name '*.c' -print0 |xargs -0 wc -l . Тем не менее, этот более быстрый метод (по крайней мере, в OS X) приводит к тому, что выводит «total» несколько раз, поэтому для получения правильного итога требуется дополнительная фильтрация (подробности я опубликовал в своем ответе).
  • 0
    Это дает преимущество работы с неограниченным количеством файлов. Отлично сработано!
Показать ещё 2 комментария
11

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

find . -name '*.php' -type f -exec cat -- {} + | wc -l
  • 2
    Я собирался опубликовать вариант этого самостоятельно (с \; вместо + поскольку я не знал об этом), этот ответ должен быть правильным.
11

только для источников:

wc `find`

для фильтрации, просто используйте grep

wc `find | grep .php$`
11

То, что вы хотите, это просто 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 ?
  • 3
    Нет, Натан. Ответы xargs не обязательно будут печатать счет как одно число. Это может просто напечатать кучу промежуточных итогов.
Показать ещё 4 комментария
8

Угадав, что никто никогда не увидит, что это похоронено сзади... Тем не менее, ни один из ответов до сих пор не сталкивается с проблемой имен файлов с пробелами. Кроме того, все, использующие xargs, терпят неудачу, если общая длина путей в дереве превышает ограничение по размеру оболочки оболочки (по умолчанию - несколько мегабайт в Linux). Вот тот, который исправляет эти проблемы довольно прямо. Подоболочка заботится о файлах с пробелами. awk суммирует поток отдельных файлов wc, поэтому никогда не должно заканчиваться пространство. Он также ограничивает файлы exec только файлами (пропусками каталогов):

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

Вы также можете попробовать CLOC (требуется Perl)

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

Как вы можете видеть, предоставленная информация намного более полезна с точки зрения разработчика, потому что она может примерно рассказать вам, насколько сложным является проект, прежде чем вы начнете работать с ним.

5

WC -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 trap (количество входящих, а не строк!!!)

  • 0
    Пожалуйста, прочтите POSIX-определение строки . С grep -c ^ вы подсчитываете количество неполных строк , и такие неполные строки не могут появиться в текстовом файле .
  • 1
    Я знаю это. На практике только последняя строка может быть неполной, потому что у нее нет EOL. Идея состоит в подсчете всех строк, включая неполную. Это очень частая ошибка, считая только полные строки. после подсчета мы думаем "почему я пропустил последнюю строчку ???". Это ответ почему, и рецепт, как это сделать правильно.
4

Это очень легко с zsh globs:

wc -l ./**/*.php

Если вы используете Bash, вам просто нужно обновить. Нет абсолютно никакой причины использовать bash.

4

Что-то другое:

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

Это отлично работает, но в текущей папке или одной из ее подпапок вам нужно иметь хотя бы один файл *.php, иначе wc stalls

  • 0
    может также переполнить ARG_MAX
4

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

find . -name '*.php' | xargs wc -l | sort -r
  • 1
    Поскольку вывод xargs wc -l является числовым, на самом деле нужно будет использовать sort -n или sort -nr .
3

Для Windows простой и быстрый инструмент LocMetrics.

  • 0
    Весьма маловероятно, что OP работает в Windows, если они используют bash.
  • 0
    Заголовок и описание вопроса @VanessaMcHale явно не требуют решения только для Unix. Таким образом, решение на основе Windows является приемлемым. Также Google указал мне на эту страницу, когда я искал подобное решение.
3

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

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

Если вам нужно всего лишь общее количество строк, пусть говорят ваши PHP файлы, вы можете использовать очень простую однострочную команду даже под Windows, если у вас установлен GnuWin32. Вот так:

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

Вам нужно указать, где именно находится find.exe, иначе Windows, на которой FIND.EXE(из старых DOS-подобных команд) будет выполняться, поскольку это, вероятно, до GnuWin32 в среде PATH и имеет разные параметры и результаты.

Обратите внимание, что в приведенной выше команде вы должны использовать обратные кавычки, а не одинарные кавычки.

  • 0
    В приведенном выше примере я использую bash для Windows вместо cmd.exe, поэтому есть прямые косые черты "/", а не обратные косые черты "\".
2

Если вы работаете в Linux (и я так понимаю), я рекомендую мой инструмент polyglot. Это значительно быстрее, чем sloccount или cloc и это более функционально, чем sloccount.

Вы можете вызвать его с

poly .

или же

poly

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

2

Вам не нужны все эти сложные и трудно запоминающиеся команды. Вам просто нужен инструмент с именем line-counter.

Быстрый обзор

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

$ 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

2

Если вы хотите сохранить его простым, вырежьте посредника и просто вызовите wc со всеми именами файлов:

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

Или в современном синтаксисе:

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

Работает до тех пор, пока в именах каталогов или именах файлов не будет пробелов. И до тех пор, пока у вас нет десятков тысяч файлов (современные оболочки поддерживают очень длинные командные строки). В вашем проекте 74 файла, поэтому у вас есть много возможностей для роста.

  • 0
    Мне нравится этот! Если вы находитесь в гибридной среде C / C ++: wc -l `find . -type f \( -name "*.cpp" -o -name "*.c" -o -name "*.h" \) -print`
  • 0
    был удивлен, что это не лучший ответ
2

Исключение пустой строки

find . -name "*.php" | xargs grep -v -c '^$' | awk 'BEGIN {FS=":"} { $cnt = $cnt + $2} END {print $cnt}'

Включая пустые строки:

find . -name "*.php" | xargs wc -l
  • 0
    не работает . ,
2

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

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

Я использовал этот inline- script, который я запускаю из каталога src-project:

 for i in $(find . -type f); do rowline=$(wc -l $i | cut -f1 -d" "); file=$(wc -l $i | cut -f2 -d" "); lines=$((lines + rowline)); echo "Lines["$lines"] " $file "has "$rowline"rows."; done && unset lines

Это производит этот вывод:

Lines[75]  ./Db.h has 75rows.
Lines[143]  ./Db.cpp has 68rows.
Lines[170]  ./main.cpp has 27rows.
Lines[294]  ./Sqlite.cpp has 124rows.
Lines[349]  ./Sqlite.h has 55rows.
Lines[445]  ./Table.cpp has 96rows.
Lines[480]  ./DbError.cpp has 35rows.
Lines[521]  ./DbError.h has 41rows.
Lines[627]  ./QueryResult.cpp has 106rows.
Lines[717]  ./QueryResult.h has 90rows.
Lines[828]  ./Table.h has 111rows.
2

В OS X, по крайней мере, команды find + xarg + wc, перечисленные в некоторых других ответах, печатают "total" несколько раз в больших списках, и нет полной полной информации. Я смог получить одно общее количество файлов .c, используя следующую команду:

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

1

Я делаю это так:

здесь реализована реализация файла lineCount.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h> 

int getLinesFromFile(const char*);

int main(int argc, char* argv[]) {
   int total_lines = 0; 
   for(int i = 1; i < argc; ++i) {
       total_lines += getLinesFromFile(argv[i]); // *argv is a char*        
   }    

   printf("You have a total of %d lines in all your file(s)\n",    total_lines);
   return 0;
}


int getLinesFromFile(const char* file_name) {
    int lines = 0;
    FILE* file;
    file = fopen(file_name, "r");
    char c = ' ';
    while((c=getc(file)) != EOF) if(c == '\n') ++lines;
    fclose(file);   
    return lines;
}

Теперь откройте командную строку:

и введите gcc lineCount.c, затем введите ./a.out *.txt Это отобразит общие строки файлов, заканчивающихся на .txt в вашем каталоге.

1

Сначала измените каталог, в который вы хотите узнать количество строк. например, если я хочу знать количество строк во всех файлах каталога с именем sample. дайте $cd sample. затем попробуйте команду $wc -l * которая вернет количество строк для каждого файла, а также общее количество строк во всем каталоге в конце

  • 0
    Это не будет считаться рекурсивно верно?
1

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

find . -name '*.js' -or -name '*.php' | xargs wc -l | grep 'total'  | awk '{ SUM += $1; print $1} END { print "Total text lines in PHP and JS",SUM }'

79351
15318
Всего текстовых строк в PHP и JS 94669

Это позволяет вам связывать несколько типов расширений, которые вы хотите фильтровать. Просто добавьте их в часть -name '*.js' -or -name '*.php' и, возможно, измените сообщение otuput по своему вкусу

1

Еще одна команда, чтобы получить сумму всех файлов (Linux, конечно)

find ./ -type f -exec wc -l {}  \; | cut -d' ' -f1 | paste -sd+ | bc

Основное отличие от других ответов:

  • с помощью find -exec,
  • с использованием пасты (с разрезом),
  • с помощью bc
  • 0
    Я немного изменил это в своем собственном ответе, чтобы работать на OS X, но разве эта версия не должна иметь «-» в качестве последнего аргумента для вставки, так что она принимает ввод из stdin? Или вставка делает это по умолчанию в Linux?
  • 0
    Это делает это по умолчанию. Извините, я не видел, что это только для OS X.
Показать ещё 3 комментария
1

У меня есть загрузочный ящик, установленный в моей системе Windows. Итак, вот что я сделал.

ECHO OFF
for /r %%G in (*.php) do (
busybox grep . "%%G" | busybox wc -l
) 
1
$cd directory
$wc -l* | sort -nr
1

очень просто

find /path -type f -name "*.php" | while read FILE
do
    count=$(wc -l < $FILE)
    echo "$FILE has $count lines"
done
  • 1
    произойдет сбой, если в одном из имен файлов есть пробел или символ новой строки
0

Если файлов слишком много, лучше просто посмотреть на общее количество.

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

Я также могу добавить еще одну запись в OS X, в которой используется простая старая находка с exec (которую я предпочитаю использовать с помощью xargs, поскольку я видел нечетные результаты из очень больших наборов результатов find с xargs в прошлом). Поскольку это для OS X, я также добавил в фильтрацию в файлы .h или .m - обязательно скопируйте все до конца!

find ./ -type f -name "*.[mh]" -exec wc -l {}  \; | sed -e 's/[ ]*//g' | cut -d"." -f1 | paste -sd+ - | bc
0

Это должно сделать то же самое, что и piping в xargs wc -l, это может быть не так быстро.

t=0
for i in $(find . -name '*.php'); do
    n=0
    while read line; do
        ((n++)) && continue
    done < $i
    ((t+=n))
    echo "$n $i"
done
echo "$t total"
0
cat \`find . -name "*.php"\` | wc -l

Ещё вопросы

Сообщество Overcoder
Наверх
Меню