Используйте find, wc и sed для подсчета строк

Я пытался использовать sed для подсчета всех строк на основе определенного расширения.

find -name '*.m' -exec wc -l {} \; | sed ...

Я пытался сделать следующее, как бы я включил sed в эту конкретную строку, чтобы получить итоги.


person Berlin Brown    schedule 11.09.2009    source источник


Ответы (8)


Вы также можете получить хорошее форматирование от wc с помощью:

wc `find -name '*.m'`
person Emmanuel BERNAT    schedule 11.09.2009
comment
Добавьте -type f, чтобы избежать случая совпадения имени каталога: wc $(find -type f -name '*.m') - person Dennis Williamson; 11.09.2009
comment
wc $(find -name '*.m') красивее. - person jason; 07.10.2016

Большинство ответов здесь не будут работать для большого количества файлов. Некоторые сломаются, если список имен файлов слишком длинный для одного вызова из командной строки, другие неэффективны, потому что -exec запускает новый процесс для каждого файла. Я считаю, что надежным и эффективным решением было бы:

find . -type f -name "*.m" -print0 | xargs -0 cat | wc -l

Использование cat таким образом нормально, так как его выходные данные передаются прямо в wc, поэтому в памяти одновременно сохраняется только небольшое количество содержимого файлов. Если файлов слишком много для одного вызова cat, cat будет вызываться несколько раз, но все выходные данные все равно будут направляться в один процесс wc.

person Daniel James    schedule 07.01.2012
comment
Или вместо этого используйте стандартную/переносимую форму: find . -type f -name '*.m' -exec cat {} + | wc -l. - person Stephane Chazelas; 05.09.2016
comment
как изменить это, чтобы распечатать общие строки для каждого файла с именем файла? - person loretoparisi; 20.09.2018

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

find . -name '*.m' -exec cat {} \; | wc -l
person sth    schedule 11.09.2009

На современных платформах GNU wc и find принимают параметры -print0 и -files0-from, которые можно объединить в команду, которая подсчитывает строки в файлах с общим количеством в конце. Пример:

find . -name '*.c' -type f -print0 | wc -l --files0-from=-
person Alexei Polkhanov    schedule 05.06.2011

вы также можете использовать sed для подсчета строк вместо wc:

 find . -name '*.m' -exec sed -n '$=' {} \;

где '$=' — это «специальная переменная», которая хранит количество строк

РЕДАКТИРОВАТЬ

вы также можете попробовать что-то вроде sloccount

person dfa    schedule 11.09.2009
comment
найти . -name '*.m' -exec sed -n 'где $=' {} \; Это все? - person Berlin Brown; 11.09.2009
comment
Это еще не все вместе взятые. - person Berlin Brown; 11.09.2009
comment
Хорошо, я закончил с этим. $ найти . -name '*.m' -exec sed -n '$=' {} \; | сумма - 22696 1 - person Berlin Brown; 11.09.2009
comment
где '$=' — это специальная переменная, которая хранит количество строк. Вы шутите, сэр! $= представляет адрес и команду. $ является последней строкой, команда = является текущим номером строки в сочетании с переключателем -n, который подавляет распечатку пространства шаблонов. В результате он подсчитывает количество переданных ему строк. - person potong; 13.12.2011
comment
@dfa Спасибо. Как напечатать имя файла до подсчета? - person loretoparisi; 20.09.2018

Хм, решение с cat может быть проблематичным, если у вас много файлов, особенно больших.

Второе решение не дает общего количества, только строки в файле, как я тестировал.

Я предпочитаю что-то вроде этого:

find . -name '*.m' | xargs wc -l | tail -1

Это сделает работу быстро, независимо от того, сколько и насколько больших файлов у вас есть.

person igustin    schedule 11.09.2009
comment
Если для одной командной строки слишком много файлов, xargs разделит их на части, и это даст общее количество только для последней части. - person Daniel James; 07.01.2012

sed не является подходящим инструментом для подсчета. Вместо этого используйте awk:

find . -name '*.m' -exec awk '{print NR}' {} +

Использование + вместо \; заставляет find вызывать awk через каждые N найденных файлов (например, с xargs).

person marco    schedule 12.09.2009
comment
Забавно, я действительно хотел сказать awk - person Berlin Brown; 14.09.2009

Для больших каталогов мы должны использовать:

find . -type f -name '*.m' -exec sed -n '$=' '{}' + 2>/dev/null | awk '{ total+=$1 }END{print total}' 

# alternative using awk twice
find . -type f -name '*.m' -exec awk 'END {print NR}' '{}' + 2>/dev/null | awk '{ total+=$1 }END{print total}' 
person Community    schedule 14.09.2009