Saída de piping de 'find' para 'xargs wc' fornece totais não razoáveis

0

Em um projeto com milhares de arquivos, eu queria comparar o total de linhas de código com linhas de código apenas em PHP (descartando CSS, JavaScript, etc.).

Quando eu corro

find . -type f | xargs wc -l

o total na última linha é menor do que quando eu corro

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

Considerando o segundo find tem que ser uma lista menor de arquivos do que (é um subconjunto estrito de) o primeiro find , como wc poderia reportar um total maior no segundo caso?

    
por Jeremy Wadhams 09.01.2013 / 17:33

3 respostas

1

xargs só pode passar ARG_MAX bytes de argumentos para wc .

No meu Mac, o ARG_MAX é menor que os nomes completos dos arquivos e os caminhos relativos dos arquivos do projeto inteiro, portanto, no comando primeiro , xargs despejou os resultados do find to wc em dois lotes , o que significa que wc colocou dois totais , rodeados por milhares de nomes de arquivos. Mas o ARG_MAX era maior do que o segundo find de saída, de modo que o segundo menor encontrou tudo em um wc total.

A correção era usar esses comandos, para que eu pudesse ver todos os totais sem as linhas de contagem de arquivos individuais (chatas):

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

Em seguida, some as várias linhas "totais" manualmente.

    
por 09.01.2013 / 17:33
0

Existem várias maneiras de fazer isso e xargs não é o melhor. Aqui está um casal:

  1. O mais simples, é cat de cada um dos arquivos encontrados por find e conta as linhas. Cuidado, isso só funciona com seus nomes de arquivos sem espaços ou caracteres estranhos:

    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 
    

    Se os seus nomes de arquivo provavelmente contiverem caracteres estranhos (barras, espaços, etc.) use isto:

    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. A melhor maneira é usar a opção -exec do find:

    find . -name "*.pep" -exec cat {} \; | wc
    find -E . -regex '.+\.(php|inc)' -type f -exec cat {} \; | wc
    
por 09.01.2013 / 18:15
0

Use awk para somar os vários números "totais" das saídas wc -l !

(Nota: wc -l retorna o número de caracteres de nova linha, isto é, "linhas" finais sem um caractere \n final não serão contadas - como é o caso de awk ou 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}'
    
por 06.12.2013 / 17:10

Tags