Compter les éléments délimités nul dans le fichier

8

J'ai un script shell qui permet find -print0d'enregistrer une liste de fichiers à traiter dans un fichier temporaire. Dans le cadre de la journalisation, j'aimerais afficher le nombre de fichiers trouvés, et j'ai donc besoin d'un moyen pour obtenir ce nombre. Si l' -print0option n'était pas utilisée pour des raisons de sécurité, je pourrais utiliser wc -lpour obtenir le décompte.

qqx
la source

Réponses:

11

Quelques options:

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

Notez que pour une entrée qui contient des données après le dernier caractère NUL (ou une entrée non vide sans caractère NUL), les trapproches compteront toujours le nombre de caractères NUL, mais les approches awk/ sed/ grepcompteront un enregistrement supplémentaire pour ces octets supplémentaires .

Stéphane Chazelas
la source
J'ai mesuré ces données sur 5 Go de données aléatoires ( head -c 5G /dev/urandom > f). Résultats: grep 1,7s (idem pour grep -Fcz '') • tr + wc-c 7,7s • tr + wc-l 7,4s • sed 34,7s • awk 1m11,7s
Socowi
@Socowi, YMMV avec l'implémentation et les paramètres régionaux. Avec GNU awk, vous voudrez définir les paramètres régionaux sur C(ou ceux qui n'utilisent pas de caractères multi-octets),LC_ALL=C awk ... < f
Stéphane Chazelas
Merci pour l'astuce. Je l' ai déjà utilisé LC_ALL=Csur sortoù il n'a pas accélérer les choses, donc Heureusement , je suis encore avoir le fichier avant: LC_ALL=C awk ...prend 6.7s.
Socowi
4

La meilleure méthode à laquelle j'ai pu penser est d'utiliser grep -zc '.*'. Cela fonctionne, mais il ne convient pas d'utiliser grep avec un motif qui correspondra à tout.

qqx
la source
1

Avec perl:

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

ou:

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

ou:

perl -nle 'print scalar unpack "(Z*)*", $_'
cuonglm
la source
Le premier comptera un enregistrement supplémentaire s'il y a des données après le dernier NUL. Les 2 autres ne fonctionnent pas si l'entrée contient des caractères de nouvelle ligne.
Stéphane Chazelas
@ StéphaneChazelas: Oh, mon mauvais. Pourriez-vous apporter une amélioration?
cuonglm
Je voudrais simplement garder le premier, et mentionner le fait qu'il compte un enregistrement non délimité (contrairement à wc -l) comme une note (comme on peut le souhaiter).
Stéphane Chazelas