Как подсчитать строки кода, включая подкаталоги [дубликат]
этот вопрос уже есть ответ здесь:
- Как рекурсивно подсчитать все строки кода в каталоге? 39 ответы
предположим, я хочу подсчитать строки кода в проекте. Если все файлы находятся в одном каталоге я могу выполнить:
cat * | wc -l
однако, если есть подкаталоги, это не работает. Для это для работы кошка должна была бы иметь рекурсивный режим. Я подозреваю, что это может быть работа для xargs, но мне интересно, есть ли более элегантное решение?
11 ответов:
во-первых, вам не нужно использовать
cat
для подсчета строк. Это антипаттерн называется бесполезное использование кошки (UUoC). Для подсчета строк в файлах в текущем каталоге используйтеwc
:wc -l *
тут повторяется на страницах каталогов:
find . -name "*.c" -exec wc -l {} \;
.
- это имя верхнего каталога для начала поиска из
-name "*.c"
- это образец файла вы заинтересованы в
-exec
дает команду для выполнения
{}
является результатом команды find, которая будет передана команде (здесьwc-l
)
\;
указывает на конец командыэта команда создает список всех найденных файлов с их количеством строк, Если вы хотите иметь сумму для все файлы, вы можете использовать найдите список файлов (с помощью
find . -name "*.c" -print | xargs wc -l
EDIT to address Robert Gamble комментарий (спасибо): если у вас есть пробелы или новые строки (!) в именах файлов, то вы должны использовать вместо
xargs -null
так что список имен файлов обмениваются с нулевыми строками.find . -name "*.c" -print0 | xargs -0 wc -l
философия Unix состоит в том, чтобы иметь инструменты, которые делают только одну вещь, и делают это что ж.
если вы хотите код-гольф ответ:
grep '' -R . | wc -l
проблема с просто использованием wc-l сама по себе это не может спуститься хорошо, и oneliners с помощью
find . -exec wc -l {} \;
не даст вам общее количество строк, потому что он запускает wc один раз для каждого файла, ( loL! ) и
find . -exec wc -l {} +
будет запутаться, как только найти хиты ~200k1,2 ограничение аргумента символа для параметров и вместо этого вызывает wc несколько раз, каждый раз только давая вам частичное резюме.
кроме того, вышеупомянутый трюк grep не добавит больше 1 строки к выходу, когда он столкнется с двоичным файлом, что может быть косвенно полезно.
за стоимость 1 дополнительного командного символа вы можете полностью игнорировать двоичные файлы:
grep '' -IR . | wc -l
если вы хотите запустить счетчик строк на двоичных файлах тоже
Сноска по теме пределы:grep '' -aR . | wc -l
документы немного расплывчаты относительно того, является ли его строка ограничение размера или количество жетонов ограничения.
cd /usr/include; find -type f -exec perl -e 'printf qq[%s => %s\n], scalar @ARGV, length join q[ ], @ARGV' {} + # 4066 => 130974 # 3399 => 130955 # 3155 => 130978 # 2762 => 130991 # 3923 => 130959 # 3642 => 130989 # 4145 => 130993 # 4382 => 130989 # 4406 => 130973 # 4190 => 131000 # 4603 => 130988 # 3060 => 95435
это означает, что его будет кусок очень очень легко.
Я думаю, что вы, вероятно, застряли с xargs
find -name '*php' | xargs cat | wc -l
хорошее объяснение на в Linux: команды xargs и в exec {}
попробуйте использовать , который повторяется в каталоги по умолчанию:
find . -type f -execdir cat {} \; | wc -l
правильный путь:
find . -name "*.c" -print0 | xargs -0 cat | wc -l
вы должны использовать -print0, потому что в именах файлов Unix есть только два недопустимых символа: нулевой байт и "/" (косая черта). Так, например," xxx\npasswd " является допустимым именем. На самом деле, вы, скорее всего, столкнетесь с именами с пробелами в них. Команды выше будут считать каждое слово как отдельный файл.
вы также можете использовать "- type f " вместо-name, чтобы ограничить поиск файлами.
использование cat или grep в приведенных выше решениях является расточительным, если вы можете использовать относительно недавние инструменты GNU, включая Bash:
wc -l --files0-from=<(find . -name \*.c -print0)Это обрабатывает имена файлов с пробелами, произвольной рекурсии и любое количество совпадающих файлов, даже если они превышают предел длины командной строки.
мне нравится использовать найти и глава вместе для "рекурсивно cat" на всех файлах в каталоге проекта, например:
find . -name "*rb" -print0 | xargs -0 head -10000
преимущество в том, что head добавит ваше имя файла и путь:
==> ./recipes/default.rb <== DOWNLOAD_DIR = '/tmp/downloads' MYSQL_DOWNLOAD_URL = 'http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.10-debian6.0-x86_64.deb' MYSQL_DOWNLOAD_FILE = "#{DOWNLOAD_DIR}/mysql-5.6.10-debian6.0-x86_64.deb" package "mysql-server-5.5" ... ==> ./templates/default/my.cnf.erb <== # # The MySQL database server configuration file. # ... ==> ./templates/default/mysql56.sh.erb <== PATH=/opt/mysql/server-5.6/bin:$PATH
полный пример здесь см. В моем блоге :
http://haildata.net/2013/04/using-cat-recursively-with-nicely-formatted-output-including-headers/
Примечание я использовал 'head -10000', ясно, что если у меня есть файлы более 10 000 строк, это приведет к усечению вывода ... однако я мог бы использовать head 100000, но для "неофициального просмотра проекта / каталога" этот подход работает очень хорошо для меня.
Если вы хотите создать только общее количество строк, а не количество строк для каждого файла что-то вроде:
find . -type f -exec wc -l {} \; | awk '{total += } END{print total}'
работает хорошо. Это избавляет вас от необходимости выполнять дальнейшую фильтрацию текста в скрипте.
вот скрипт 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` 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
наслаждайтесь! -- Curran