Почему утилита wc генерирует несколько строк с «total»? - PullRequest
6 голосов
/ 23 марта 2010

Я использую утилиту wc в сценарии оболочки, который я запускаю из Cygwin, и я заметил, что в выводе есть более одной строки с "total".

Следующая функция используется для подсчета количества строк в моих исходных файлах:

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

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

Итак, это ошибка в wc или в Cygwin? Или что-то другое? На man-странице wc написано:

Печать количества строк, слов и байтов для каждого ФАЙЛА и итоговой строки, если указано более одного ФАЙЛА.

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

Ответы [ 4 ]

5 голосов
/ 23 марта 2010

Происходит то, что xargs работает wc несколько раз.xargs по умолчанию объединяет столько аргументов, сколько может, при каждом вызове команды, которую он должен выполнить, но если файлов слишком много, он будет запускать команду несколько раз для подмножеств файлов.

Есть несколько способов исправить это.Первый, который сломается, если у вас слишком много файлов, это пропустить xargs и использовать оболочку.Это может не сработать на Cygwin, но будет выглядеть так:

wc -l $(find . '(' -name '*.vb' -o -name '*.cs' ')' \
    -a '!' -iname '*.Designer.*' -a '!' -iname '.svn' )

, и вы также потеряете возможности print0.

Другой вариант - использовать awk (или perl) скрипт для обработки вывода вашей find / xargs комбо, пропуска строки «итого» и подведения итогов самостоятельно.

3 голосов
/ 23 марта 2010

Вы вызываете wc несколько раз - по одному разу для каждого «пакета» входных аргументов, предоставляемых xargs. Вы получаете одну сумму за партию.

Одной из альтернатив является использование временного файла и опция --files0-from для wc:

$ find . '(' -name '*.vb' -o -name '*.cs' ')' -a '!' -iname '*.Designer.*' -a 
    '!' -iname   '.svn' -print0 > files

$ wc --files0-from files
2 голосов
/ 20 ноября 2013

Длина командной строки в cygwin намного более ограничена, чем в стандартном Linux-боксе, и xargs должен разделить ввод для соблюдения этих ограничений. Вы можете проверить пределы с помощью xargs --show-limits:

На Cygwin:

$ xargs --show-limits < /dev/null
Your environment variables take up 4913 bytes
POSIX upper limit on argument length (this system): 25039
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 20126
Size of command buffer we are actually using: 25039

По центам:

$ xargs --show-limits < /dev/null
Your environment variables take up 1816 bytes
POSIX upper limit on argument length (this system): 2617576
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2615760
Size of command buffer we are actually using: 131072

И, основываясь на ответе @ JonSkeet, вам не нужно создавать дополнительный файл, вы можете направить результаты поиска непосредственно в wc, передав - в качестве аргумента --files0-from:

find . -name '*.vb' -print0 | wc -l --files0-from=-
0 голосов
/ 08 декабря 2013

Чтобы избежать генерации нескольких строк с «общим» количеством при вводе утилиты wc с огромным количеством путей к файлам в качестве аргументов командной строки, вы можете использовать промежуточное значение от xargs до cat содержимого файлов для стандартный wc (см. вывод команды find для xargs wc дает необоснованные итоги ).

Это обходной путь, если ваша команда wc не имеет --files0-from, как упомянуто Ксавье.

count_curdir_src() (
   export LC_ALL=C
   find . -name '*.vb' -print0 | xargs -0 -n 1000 cat | wc -l 
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...