Я использую утилиту туалета в сценарии оболочки, который я выполняю из Cygwin, и я заметил, что существует больше чем одна строка с "общим количеством" в ее выводе.
Следующая функция используется для подсчета количества строк в моих исходных файлах:
count_curdir_src() {
find . '(' -name '*.vb' -o -name '*.cs' ')' \
-a '!' -iname '*.Designer.*' -a '!' -iname '.svn' -print0 | \
xargs -0 wc -l
}
Но его вывод для определенного каталога похож на это:
$ find . '(' -name '*.vb' -o -name '*.cs' ')' -a '!' -iname '*.Designer.*' -a '!' -iname '.svn' -print0 | xargs -0 wc -l
19 ./dirA/fileABC.cs
640 ./dirA/subdir1/fileDEF.cs
507 ./dirA/subdir1/fileGHI.cs
2596 ./dirA/subdir1/fileJKL.cs
(...many others...)
58 ./dirB/fileMNO.cs
36 ./dirB/subdir1/filePQR.cs
122200 total
6022 ./dirB/subdir2/subsubdir/fileSTU.cs
24 ./dirC/fileVWX.cs
(...)
36 ./dirZ/Properties/AssemblyInfo.cs
88 ./dirZ/fileYZ.cs
25236 total
Это похоже на сброс туалета где-нибудь в процессе. Это не может быть вызвано пробелами в именах файлов или именах каталогов, потому что я использую -print0
опция. И это только происходит, когда я выполняю его на своем дереве крупнейшего источника.
Так, действительно ли это - ошибка в туалете, или в Cygwin? Или что-то еще? В странице справочника туалета говорится:
Распечатайте новую строку, слово и счета байта для каждого ФАЙЛА и общей строки, если больше чем один ФАЙЛ указан.
Это ничего не упоминает о нескольких общих строках (промежуточное общее количество рассчитывает или что-то), поэтому кто виноват здесь?
Вы вызываете wc несколько раз - по одному для каждого «пакета» входных аргументов, предоставленных xargs. Вы получаете одну сумму за партию.
Один из альтернативных вариантов - использовать временный файл и параметр - files0-from
для wc
:
$ find . '(' -name '*.vb' -o -name '*.cs' ')' -a '!' -iname '*.Designer.*' -a
'!' -iname '.svn' -print0 > files
$ wc --files0-from files
Что происходит, так это то, что xargs
запускает wc
несколько раз. xargs
по умолчанию объединяет столько аргументов, сколько считает возможным, при каждом вызове команды, которую он должен запустить, но если файлов слишком много, он будет запускать команду несколько раз для подмножеств файлов.
Я вижу несколько способов исправить это. Первый, который сломается, если у вас слишком много файлов, - это пропустить xargs
и использовать оболочку. Это может плохо работать в Cygwin, но будет выглядеть так:
wc -l $(find . '(' -name '*.vb' -o -name '*.cs' ')' \
-a '!' -iname '*.Designer.*' -a '!' -iname '.svn' )
и вы также потеряете возможности print0.
Другой - использовать сценарий awk
(или perl
) для обработки вывода вашей комбинации find
/ xargs
, пропустите «итоговые» строки и просуммируйте итоги самостоятельно.