В проекте с тысячами файлов я хотел сравнить общее количество строк кода со строками кода только в PHP (исключая CSS, JavaScript и т.д.).

Когда я бегу

find . -type f | xargs wc -l

сумма на последней строке ниже, чем когда я бегу

find -E . -regex '.+\.(php|inc)' -type f | xargs wc -l

Учитывая, что вторая find должна быть меньшим списком файлов, чем (является строгим подмножеством) первой find , как wc может сообщить о более высоком общем количестве во втором случае?

3 ответа3

1

xargs может передавать только ARG_MAX байт аргументов wc

На моем Mac ARG_MAX меньше, чем полные имена файлов и относительные пути файлов всего проекта, поэтому в первой команде xargs результаты find в wc в двух пакетах, что означает, что wc выдает два итога в окружении тысячами имен файлов. Но оказалось, что ARG_MAX больше, чем результат второго find , поэтому вторая, более мелкая находка показала все в одном wc .

Исправление было в том, чтобы использовать эти команды, чтобы я мог видеть все итоги без (скучных) отдельных строк подсчета файлов:

find . -type f | xargs wc -l | grep total
find -E . -regex '.+\.(php|inc)' -type f | xargs wc -l | grep total

Затем сложите несколько "итоговых" строк вручную.

0

Используйте awk для суммирования различных "общих" чисел выводов wc -l !

(Примечание: wc -l возвращает количество символов новой строки, т.е. окончательные "строки" без последнего символа \n не будут учитываться - как в случае с awk или sed .)

export LC_ALL=C
find . -type f -print0 | xargs -0 wc -l | 
    awk '/^ *[[:digit:]]+ total$/{ total+=$1 }END{print total}'


# xargs alternatives using: find ... -exec <wc|awk|sed> ... '{}' +
#man find | less -p '{} \+'

# wc
find . -type f -exec wc -l '{}' + 2>/dev/null | 
   awk '/^ *[[:digit:]]+ total$/{ total+=$1 }END{print total}'

# awk
find . -type f -exec awk 'END {print NR}' '{}' + 2>/dev/null | 
    awk '{ total+=$1 }END{print total}'

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

Есть много способов сделать это, и xargs не самый лучший. Вот пара:

  1. Самое простое, это cat каждый из найденных файлов путем find и подсчета строк. Осторожно, это работает только с именами ваших файлов без пробелов и странных символов:

    find . -type f | while read n; do cat $n; done | wc -l
    find -E . -regex '.+\.(php|inc)' -type f | while read n; do cat $n; done | wc -l 
    

    Если ваши имена файлов могут содержать странные символы (косые черты, пробелы и т.д.), Используйте это вместо:

    find . -type f | while IFS= read -r n; do cat $n; done | wc -l
    find -E . -regex '.+\.(php|inc)' -type f | while IFS= read -r n; do cat $n; done | wc -l 
    
  2. Лучше использовать опцию find -exec :

    find . -name "*.pep" -exec cat {} \; | wc
    find -E . -regex '.+\.(php|inc)' -type f -exec cat {} \; | wc
    

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .