89 votes

Comment compter les lignes de code, y compris les sous-répertoires ?

Supposons que je veuille compter les lignes de code d'un projet. Si tous les fichiers sont dans le même répertoire, je peux exécuter :

cat * | wc -l

Cependant, s'il y a des sous-répertoires, cela ne fonctionne pas. Pour que cela fonctionne, il faudrait que cat ait un mode récursif. Je pense que cela pourrait être un travail pour xargs, mais je me demande s'il existe une solution plus élégante ?

154voto

philant Points 17345

Tout d'abord, vous n'avez pas besoin d'utiliser cat pour compter les lignes. Il s'agit d'un anti-modèle appelé Utilisation inutile du chat (UUoC). Pour compter les lignes des fichiers dans le répertoire courant, utilisez wc :

wc -l * 

Ensuite, le find parcourt les sous-répertoires :

find . -name "*.c" -exec wc -l {} \;
  • . est le nom du répertoire principal à partir duquel la recherche doit commencer.

  • -name "*.c" est le modèle du fichier qui vous intéresse

  • -exec donne une commande à exécuter

  • {} est le résultat de la commande find à passer à la commande (ici wc-l )

  • \; indique la fin de la commande

Cette commande produit une liste de tous les fichiers trouvés avec leur nombre de lignes, si vous voulez avoir la somme pour todo les fichiers trouvés, vous pouvez utiliser find pour lister les fichiers (avec la balise -print ) et ensuite utiliser xargs pour passer cette liste comme argument à wc-l.

find . -name "*.c" -print | xargs wc -l 

EDIT pour répondre au commentaire de Robert Gamble (merci) : si vous avez des espaces ou des retours à la ligne ( !) dans les noms de fichiers, alors vous devez utiliser -print0 au lieu de l'option -print y xargs -null afin que la liste des noms de fichiers soit échangée avec des chaînes de caractères à terminaison nulle.

find . -name "*.c" -print0 | xargs -0 wc -l

La philosophie d'Unix est d'avoir des outils qui font une seule chose, et qui la font bien.

30voto

Kent Fredric Points 35592

Si vous voulez une réponse de type "code-golf" :

grep '' -R . | wc -l 

Le problème avec l'utilisation de wc -l seul est qu'il ne peut pas bien descendre, et les oneliners utilisant

find . -exec wc -l {} \;

Il ne vous donnera pas le nombre total de lignes car il exécute wc une fois pour chaque fichier, ( loL ! ) et

find . -exec wc -l {} + 

Je vais m'embrouiller dès que Find atteindra les 200 000 euros. 1 , 2 limite de caractères pour les paramètres et appelle à la place wc multiple fois, en ne vous donnant à chaque fois qu'un résumé partiel.

De plus, l'astuce grep ci-dessus n'ajoutera pas plus d'une ligne à la sortie lorsqu'elle rencontrera un fichier binaire, ce qui pourrait être bénéfique pour les circonstances.

Au prix d'un caractère de commande supplémentaire, vous pouvez ignorer complètement les fichiers binaires :

 grep '' -IR . | wc -l

Si vous souhaitez également effectuer des comptages de lignes sur des fichiers binaires

 grep '' -aR . | wc -l 

Note de bas de page sur les limites :

Les documents sont un peu vagues quant à savoir s'il s'agit d'une chaîne de caractères ou une limite de taille nombre de jetons limite.

cd /usr/include;
find -type f -exec perl -e 'printf qq[%s => %s\n], scalar @ARGV, length join q[ ], @ARGV' {} + 
# 4066 => 130974
# 3399 => 130955
# 3155 => 130978
# 2762 => 130991
# 3923 => 130959
# 3642 => 130989
# 4145 => 130993
# 4382 => 130989
# 4406 => 130973
# 4190 => 131000
# 4603 => 130988
# 3060 => 95435

Cela implique qu'il va se briser très très facilement.

13voto

Ken Points 23619

Je pense que vous êtes probablement coincé avec xargs

find -name '*php' | xargs cat | wc -l

chromakode La méthode de l'UE donne le même résultat mais est beaucoup plus lente. Si vous utilisez xargs, votre chat et wc peut commencer dès que trouver commence à trouver.

Bonne explication à Linux : xargs vs. exec {}

10voto

chromakode Points 328

Essayez d'utiliser le find qui récure les répertoires par défaut :

find . -type f -execdir cat {} \; | wc -l

10voto

Aaron Digulla Points 143830

Le bon chemin est :

find . -name "*.c" -print0 | xargs -0 cat | wc -l

Vous devez utiliser -print0 car il n'y a que deux caractères invalides dans les noms de fichiers Unix : L'octet nul et "/" (barre oblique). Donc par exemple "xxx \npasswd "est un nom valide. En réalité, il est plus probable que vous rencontriez des noms contenant des espaces. Les commandes ci-dessus considèrent chaque mot comme un fichier distinct.

Vous pouvez également utiliser "-type f" au lieu de -name pour limiter la recherche aux fichiers.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X