Contar nul itens delimitados no arquivo

8

Eu tenho um script de shell que usa find -print0para salvar uma lista de arquivos a serem processados ​​em um arquivo temporário. Como parte do registro, gostaria de gerar o número de arquivos encontrados e, portanto, preciso de uma maneira de obter essa contagem. Se a -print0opção não estivesse sendo usada por segurança, eu poderia usar wc -lpara obter a contagem.

qqx
fonte

Respostas:

11

Algumas opções:

tr -cd '\0' | wc -c

tr '\n\0' '\0\n' | wc -l      # Generic approach for processing NUL-terminated
                              # records with line-based utilities (that support
                              # NUL characters in their lines like GNU ones).

grep -cz '^'                  # GNU grep

sed -nz '$='                  # recent GNU sed, no output for empty input

awk -vRS='\0' 'END{print NR}' # not all awk implementations

Observe que, para uma entrada que contenha dados após o último caractere NUL (ou entrada não vazia sem caracteres NUL), as trabordagens sempre contarão o número de caracteres NUL, mas as abordagens awk/ sed/ grepcontarão um registro extra para esses bytes extras .

Stéphane Chazelas
fonte
Eu os medi em 5 GB de dados aleatórios ( head -c 5G /dev/urandom > f). Resultados: grep 1.7s (igual para grep -Fcz '') • tr + wc-c 7.7s • tr + wc-l 7.4s • sed 34.7s • awk 1m11.7s
Socowi 23/04
@Socowi, YMMV com a implementação e localidade. Com o GNU awk, você desejará definir o código do idioma para C(ou qualquer um que não use caracteres multibyte),LC_ALL=C awk ... < f
Stéphane Chazelas
Obrigado pela dica. Eu já utilizado LC_ALL=Cem sortonde não fez acelerar as coisas, portanto Felizmente eu ainda tenho o arquivo de antes: LC_ALL=C awk ...leva 6.7s.
Socowi 23/04
4

O melhor método em que consegui pensar é usar grep -zc '.*'. Isso funciona, mas parece errado usar grep com um padrão que corresponda a qualquer coisa.

qqx
fonte
1

Com perl:

perl -0ne 'END {print $.}'

ou:

perl -nle 'print scalar split "\0"'

ou:

perl -nle 'print scalar unpack "(Z*)*", $_'
cuonglm
fonte
O primeiro contará um registro extra se houver dados após o último NUL. Os outros 2 não funcionam se a entrada contiver caracteres de nova linha.
Stéphane Chazelas 4/14
@ StéphaneChazelas: Oh, meu mal. Você poderia dar alguma melhoria?
amigos estão dizendo sobre cuonglm
Gostaria apenas de manter o primeiro e mencionar o fato de que ele conta um registro não-delimitado (ao contrário de wc -l) como uma nota (como pode ser desejado).
Stéphane Chazelas 4/14