/ bin / cat: Lista de argumentos muito longa

4

Eu tenho 119766 arquivos em uma pasta. Eles são arquivos CSV. Eu quero descobrir o número total de linhas de todos os arquivos.

Estou tentando executar o seguinte comando:

cat * |wc -l

Mas o seguinte erro ocorre:

-bash: /bin/cat: Argument list too long

Como posso fazer isso? Existe alguma maneira de contornar isso?

Uma coisa que gostaria de acrescentar é que o número total de linhas seria muito grande.

    
por Milon Corleone 01.03.2016 / 05:43

3 respostas

5

Se você quiser uma contagem de linhas para cada arquivo individual:

find . -type f -exec wc -l {} + | awk '! /^[ 0-9]+[[:space:]]+total$/'

Excluímos o total de linhas porque haverá várias delas com muitos arquivos sendo processados. O find ... -exec ... + tentará encaixar tantos nomes de arquivos em uma única linha de comando quanto possível, mas isso será muito menor que 119766 arquivos ... provavelmente apenas alguns milhares (no máximo) por invocação de wc , e cada um um resultará em sua própria linha 'total' independente.

Se você quiser o número total de linhas em todos os arquivos combinados, aqui está uma maneira de fazer isso:

find . -type f -exec wc -l {} + | 
    awk '/^[ 0-9]+[[:space:]]+total$/ {print $1}' | 
    xargs | sed -e 's/ /+/g' | bc

Isso imprime apenas as contagens de linha no total de linhas, os pipes em xargs para obter todas as contagens em uma linha, depois sed para transformar os espaços em + signs e, em seguida, canaliza o lote para bc para fazer o cálculo.

Exemplo de saída:

$ cd /usr/share/doc
$ find . -type f -exec wc -l {} + | 
    awk '/^[ 0-9]+[[:space:]]+total$/ {print $1}' | 
    xargs | sed -e 's/ /+/g' | bc 
53358931
    
por 01.03.2016 / 05:58
6

Bem, para dar a cat da questão uma nova casa, isso deve ser feito:

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

Executa um cat com o número máximo aceitável de nomes de arquivos ( + ) novamente e canaliza tudo para wc . Se você não deseja percorrer subdiretórios, um -maxdepth 1 deve ser adicionado ao comando find, após o diretório.

Como alternativa, a opção --files0-from para o GNU wc poderia ser usada:

find . -type f -print0 | wc -l --files0-from=- | tail -1

Esta opção faz com que wc não leia o conteúdo, mas os nomes de arquivos do stdin, separados por caracteres nulos. Com -print0 , find imprimirá esses nomes de arquivos separados por byte nulo. Como wc ainda irá imprimir as contagens de linha para cada arquivo, é aconselhável pular tudo, exceto a linha de resumo no final, daí o tail .

As duas soluções têm a vantagem de funcionar em qualquer localidade, enquanto as soluções do @cas precisam ser adaptadas ('total' é 'insgesamt' em alemão, por exemplo).

    
por 01.03.2016 / 11:03
0

Se você tiver muitos arquivos, provavelmente não desejará que as informações sejam enviadas para o stdout, para que você possa fazer algo assim:

IFS="\n"; for file in find ./ -type f; do wc -l "$file" >> ~/linecount.txt; done
    
por 01.03.2016 / 05:59