Encontrando o número de linhas usando o comando find

6

Considere o repositório de código-fonte R encontrado em link . Eu descompactei o repositório em uma pasta. Agora, desejo descobrir quantas linhas totais existem no diretório. Então, eu tentei o seguinte comando:

find . -type f -exec wc -l {} \+

que rende 394968 mas se eu tentar o seguinte comando:

find . -type f -exec cat {} \+ | wc -l

rende 1848857!

Por que essas duas operações aparentemente semelhantes do comando find estão produzindo resultados tão drasticamente diferentes? E qual é a maneira correta de encontrar o número de linhas, preferencialmente usando utilitários de linha de comando em vez de criar scripts para uma pequena ferramenta?

    
por Vijay 16.04.2018 / 19:46

1 resposta

13

O primeiro comando que você mencionou, find . -type f -exec wc -l {} + , realmente diz "execute wc -l no maior número de arquivos possível, até que todos eles foram processados ". Isso pode executar wc várias vezes!

Por outro lado, find . -type f -exec cat {} + | wc -l pode ser executado cat várias vezes, mas só executará wc uma vez. (Mais em detalhe, isto porque neste caso cat é chamado por find , o que pode e decide executá-lo quantas vezes quiser, enquanto a parte depois que o caractere de pipe, wc -l , estiver além do alcance de find e é, portanto, executado pelo seu shell, apenas uma vez.)

Você diz que o primeiro comando "rende 394968", mas realmente não; no meu sistema sua saída termina com:

(Many more lines elided...)
     23 ./po/Makefile.win
     64 ./po/README
      1 ./VERSION-NICK
     97 ./README
 258450 total

No entanto, adicionando grep total , pode-se ver que wc foi realmente executado duas vezes:

$ find . -type f -exec wc -l {} + | grep total
 1590407 total
 258450 total

E, de fato, 1590407 mais 258450 é 1848857, o que concorda com o segundo comando.

Uma explicação de por que wc foi executado mais de uma vez na versão find -exec wc + do comando é vagamente insinuado por a página do manual do encontro :

-exec command {} +

    This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invocations of the command will be much less than the number of matched files.  The command line is built in much the same way that xargs builds its command lines.

Observe como isso diz "muito menos que ..." em vez de "apenas uma vez". o A documentação para xargs sugere que sua opção --max-chars está definida automaticamente se não for definido pelo usuário:

--max-chars=max-chars
-s max-chars

    Use at most max-chars characters per command line, including the command and initial-arguments and the terminating nulls at the ends of the argument strings.  The largest allowed value is system-dependent, and is calculated as the argument length limit for exec, less the size of your environment, less 2048 bytes of headroom. If this value is more than 128KiB, 128Kib is used as the default value; otherwise, the default value is the maximum.

Isso limita a quantidade de nomes de arquivos que podem ser passados para uma única chamada para wc , explicando por que, para um grande número de arquivos, várias chamadas para wc ocorrem, cada um operando em uma partição da entrada.

    
por 16.04.2018 / 20:00