conta le righe di codice (non vuote) in bash


151

In Bash, come posso contare il numero di righe di codice non vuote in un progetto?


1
Molte delle soluzioni seguenti funzionano solo per un file (ad es foo.c.). Qualche idea sul numero totale di righe in un progetto (ad es. Molti file nella struttura di directory ed escludendo i file binari)?
solvingPuzzles

5
@solvingPuzzles Penso di poter rispondere a quella parte. Per qualsiasi soluzione che funziona su un file, ad esempio "cat FILE | sed blah", puoi lavorare su molti file sostituendo "cat FILE" con un comando che elenca i nomi dei file su cui operare, ad esempio "find. -Name '* .py '"e inseriscilo in" xargs cat ". es. "find. -name '* .py' | xargs cat | sed '/ ^ \ s * $ / d' | wc -l"
Jonathan Hartley,

2
@JonathanHartley @solvingPuzzles ci sono anche programmi simili sloce clocche sono qui per fare il conteggio delle righe di codice.
AsTeR,

OP qui: quando ho chiesto per la prima volta questo problema, 'cloc' non ha fatto un ottimo lavoro sul codice Python. Oggi è fantastico.
Jonathan Hartley,

cloc è disponibile anche come modulo npm e consente di risparmiare molto tempo.
Krishna Vedula,

Risposte:


193
cat foo.c | sed '/^\s*$/d' | wc -l

E se consideri i commenti righe vuote:

cat foo.pl | sed '/^\s*#/d;/^\s*$/d' | wc -l

Anche se dipende dalla lingua.


24
Non so perché stai usando il gatto lì. Usa foo.c o foo.pl come nome file per passare a sed. sed '/ ^ \ s * $ / d' foo.c | wc -l
Andy Lester,

28
Solo abitudine. Ho letto le pipeline da sinistra a destra, il che significa che di solito inizio con cat, quindi action, action, action, ecc. Chiaramente, il risultato finale è lo stesso.
Michael Cramer,

32
Per fare questo per tutti i file in tutte le sottocartelle ed escludere i commenti con '//', estendi questo comando in questo: trova. -type f -name '* .c' -exec cat {} \; | sed '/ ^ \ s * # / d; / ^ \ s * $ / d; / ^ \ s * \ / \ // d' | wc -l
Benjamin Intal

11
Si può leggere da sinistra a destra senza UUOC: < foo.pl sed 'stuff' | wc -l.
jw013,

22
In generale, UUOC non è importante, ma la leggibilità lo è.
andersand,

52
#!/bin/bash
find . -path './pma' -prune -o -path './blog' -prune -o -path './punbb' -prune -o -path './js/3rdparty' -prune -o -print | egrep '\.php|\.as|\.sql|\.css|\.js' | grep -v '\.svn' | xargs cat | sed '/^\s*$/d' | wc -l

Quanto sopra ti fornirà il conteggio totale delle righe di codice (righe vuote rimosse) per un progetto (cartella corrente e tutte le sottocartelle in modo ricorsivo).

Nel precedente "./blog" "./punbb" "./js/3rdparty" e "./pma" sono le cartelle che inserisco nella blacklist perché non ho scritto il codice in esse. Anche .php, .as, .sql, .css, .js sono le estensioni dei file esaminati. Tutti i file con un'estensione diversa vengono ignorati.


1
variante per un'app Rails: trova. -path './log' -prune -o -path './trunk' -prune -o -path './branches' -prune -o -path './vendor' -prune -o -path './tmp '-prune -o -print | egrep '\ .rb | \ .erb | \ .css | \ .js | \ .yml' | grep -v 'svn' | gatto xargs | sed '/ ^ \ s * $ / d' | wc -l
poseid

1
Devi aggiungere $a grep ( ...\.js$|...) altrimenti corrisponderà feature.js.swp.
Xeoncross,

Hai dimenticato l'ancoraggio, quindi include file errati. E una versione ancora più semplice con l'ancoraggio:find . | egrep '.\.c$|.\.h$' | xargs cat | sed '/^\s*$/d' | wc -l
Mark Jeronimus il

36

Se vuoi usare qualcosa di diverso da uno script di shell, prova CLOC :

cloc conta le righe vuote, le righe di commento e le righe fisiche del codice sorgente in molti linguaggi di programmazione. È scritto interamente in Perl senza dipendenze al di fuori della distribuzione standard di Perl v5.6 e successive (il codice di alcuni moduli esterni è incorporato in cloc) e quindi è abbastanza portatile.


2
Quando ho posto questa domanda per la prima volta, 'cloc' ha contato i docstring di Python come righe di codice, che era IMHO non ottimale. Le versioni moderne di 'cloc' ora contano le dotstring di Python come commenti, che mi piacciono molto di più.
Jonathan Hartley,

Questa è la risposta corretta! Ho appena provato a chiudere e fa bene il lavoro.
LeeMobile,

31

Esistono molti modi per farlo, utilizzando le utilità di shell comuni.

La mia soluzione è:

grep -cve '^\s*$' <file>

Questo cerca le righe in <file> le righe non corrispondenti (-v) che corrispondono al modello (-e) '^ \ s * $', che è l'inizio di una riga, seguito da 0 o più caratteri spazi bianchi, seguito entro la fine di una riga (ovvero nessun contenuto diverso dagli spazi bianchi) e visualizza un conteggio delle righe corrispondenti (-c) invece delle stesse righe corrispondenti.

Un vantaggio di questo metodo rispetto ai metodi che prevedono il piping in wcè che puoi specificare più file e ottenere un conteggio separato per ogni file:

$ grep -cve '^\s*$' *.hh

config.hh:36
exceptions.hh:48
layer.hh:52
main.hh:39

2
Grazie! Per inciso, wc fornisce un conteggio per ogni dato file, più un totale.
Jonathan Hartley,

1
Non se stai eseguendo il piping in esso, tuttavia, come standard in un solo file.
SpoonMeiser,

Questa è la migliore risposta secondo me.
simhumileco,

-enon è necessario. Questa è la normale posizione posizionale del pattern e non stai facendo nulla di strano. Ma niente di sbagliato nell'essere esplicito, se questo è il tuo stile.
Jacktose,

13

'wc' conta linee, parole, caratteri, quindi per contare tutte le linee (comprese quelle vuote) usa:

wc *.py

Per filtrare le righe vuote, puoi usare grep:

grep -v '^\s*$' *.py | wc

'-v' dice a grep di produrre tutte le righe tranne quelle che corrispondono a '^' è l'inizio di una riga '\ s *' è zero o più caratteri di spazi bianchi '$' è la fine di una riga * .py è il mio esempio per tutti i file che si desidera contare (tutti i file Python nella directory corrente) restituiscono l'output al wc. Vai via.

Sto rispondendo alla mia (vera) domanda. Impossibile trovare una voce di StackOverflow che trattasse questo.


5
\ W non corrisponde a spazi bianchi, ma corrisponde a caratteri non di parole. È l'opposto di \ w, caratteri di parole. \ W Corrisponderà a tutto ciò che non è alfanumerico o di sottolineatura e pertanto non farà ciò che si afferma faccia qui. Intendi \ s
SpoonMeiser il

9

Questo comando conta il numero di righe non vuote.
cat fileName | grep -v ^$ | wc -l
grep -v ^ $ la funzione di espressione regolare ignora le righe vuote.


Questa risposta è la più semplice
samthebest

2
Non catgrep -v ^$ fileName | wl -l
ce n'è

7
Non è inoltre necessario wc -lperché grep ha -c:grep -vc ^$ fileName
Jacktose il


5
cat 'filename' | grep '[^ ]' | wc -l

dovrebbe fare il trucco bene


3
Perché usare cat e pipe il file in grep, quando è possibile passare il nome del file come argomento per grep in primo luogo?
SpoonMeiser,

vero, è solo un vecchio alias che ho intorno ... fa essenzialmente lo stesso della tua soluzione invece di usare l'inverso
curtisk

4
awk '/^[[:space:]]*$/ {++x} END {print x}' "$testfile"

1
Voterei questo solo perché non ho mai visto nessuno usare il preincremento in uno script awk, ma sfortunatamente questo conta solo le righe vuote. :) Vuoi dire awk '!/^[[:space:]]*$/{++x} END{print x}'. O, se davvero odi i negativi awk '{y++} /^[[:space:]]*$/{++x} END{print y-x}',;)
dannysauer,

4
grep -cvE '(^\s*[/*])|(^\s*$)' foo

-c = count
-v = exclude
-E = extended regex
'(comment lines) OR (empty lines)'
where
^    = beginning of the line
\s   = whitespace
*    = any number of previous characters or none
[/*] = either / or *
|    = OR
$    = end of the line

Pubblico questo perché altre opzioni mi hanno dato risposte sbagliate. Questo ha funzionato con la mia fonte java, dove le righe di commento iniziano con / o * (uso * su ogni riga del commento su più righe).


Questa è una soluzione praticabile. L'unica cosa da notare: non conta i commenti su più righe
Amol,

2

Ecco uno script Bash che conta le righe di codice in un progetto. Attraversa ricorsivamente un albero di origine ed esclude righe vuote e commenti a riga singola che utilizzano "//".

# $excluded is a regex for paths to exclude from line counting
excluded="spec\|node_modules\|README\|lib\|docs\|csv\|XLS\|json\|png"

countLines(){
  # $total is the total lines of code counted
  total=0
  # -mindepth exclues the current directory (".")
  for file in `find . -mindepth 1 -name "*.*" |grep -v "$excluded"`; do
    # First sed: only count lines of code that are not commented with //
    # Second sed: don't count blank lines
    # $numLines is the lines of code
    numLines=`cat $file | sed '/\/\//d' | sed '/^\s*$/d' | wc -l`

    # To exclude only blank lines and count comment lines, uncomment this:
    #numLines=`cat $file | sed '/^\s*$/d' | wc -l`

    total=$(($total + $numLines))
    echo "  " $numLines $file
  done
  echo "  " $total in total
}

echo Source code files:
countLines
echo Unit tests:
cd spec
countLines

Ecco come appare l'output per il mio progetto :

Source code files:
   2 ./buildDocs.sh
   24 ./countLines.sh
   15 ./css/dashboard.css
   53 ./data/un_population/provenance/preprocess.js
   19 ./index.html
   5 ./server/server.js
   2 ./server/startServer.sh
   24 ./SpecRunner.html
   34 ./src/computeLayout.js
   60 ./src/configDiff.js
   18 ./src/dashboardMirror.js
   37 ./src/dashboardScaffold.js
   14 ./src/data.js
   68 ./src/dummyVis.js
   27 ./src/layout.js
   28 ./src/links.js
   5 ./src/main.js
   52 ./src/processActions.js
   86 ./src/timeline.js
   73 ./src/udc.js
   18 ./src/wire.js
   664 in total
Unit tests:
   230 ./ComputeLayoutSpec.js
   134 ./ConfigDiffSpec.js
   134 ./ProcessActionsSpec.js
   84 ./UDCSpec.js
   149 ./WireSpec.js
   731 in total

Godere! - Curran


1

Dipende dal numero di file presenti nel progetto. In teoria potresti usare

grep -c '.' <list of files>

Dove è possibile compilare l'elenco dei file utilizzando l'utilità di ricerca.

grep -c '.' `find -type f`

Ti darebbe un conteggio di riga per file.


1
. corrisponde agli spazi bianchi. Questa soluzione funziona solo se consideri che una riga contenente solo spazi bianchi non è vuota, cosa che tecnicamente è, sebbene probabilmente non sia ciò che stai cercando.
SpoonMeiser,

1

Script per contare ricorsivamente tutte le righe non vuote con una determinata estensione di file nella directory corrente:

#!/usr/bin/env bash
(
echo 0;
for ext in "$@"; do
    for i in $(find . -name "*$ext"); do
        sed '/^\s*$/d' $i | wc -l ## skip blank lines
        #cat $i | wc -l; ## count all lines
        echo +;
    done
done
echo p q;
) | dc;

Esempio di utilizzo:

./countlines.sh .py .java .html

Grazie a @Andy Lester (+1 sul tuo commento) per la parte "non vuota" della ricetta.
Keith Pinson,

Grazie anche a @Michael Cramer (+1 sul tuo post) per aver pubblicato la soluzione "non vuota" (leggermente più dettagliata).
Keith Pinson,

1

Se si desidera la somma di tutte le righe non vuote per tutti i file di una determinata estensione nel corso di un progetto:

while read line
do grep -cve '^\s*$' "$line"
done <  <(find $1 -name "*.$2" -print) | awk '{s+=$1} END {print s}'

Il primo argomento è la directory di base del progetto, il secondo è l'estensione del file. Esempio di utilizzo:

./scriptname ~/Dropbox/project/src java

È poco più di una raccolta di soluzioni precedenti.


Questo ottiene il premio per il maggior numero di chiamate fork + exec avviando grep una volta per riga in ciascun file. ;)
dannysauer,

0
grep -v '^\W*$' `find -type f` | grep -c '.' > /path/to/lineCountFile.txt

fornisce un conteggio aggregato per tutti i file nella directory corrente e nelle sue sottodirectory.

HTH!


\ W è caratteri non di parole; questo non corrisponderà a una linea come ${-[*]} + $@, ad esempio. Che è sicuramente un codice valido da qualche parte nel mondo. ;) Intendi \ s per spazio.
dannysauer,

0

Ciò fornisce il conteggio del numero di righe senza contare le righe vuote:

grep -v ^$ filename wc -l | sed -e 's/ //g' 

0
rgrep . | wc -l

fornisce il conteggio delle righe non vuote nella directory di lavoro corrente.


-3

Esiste già un programma per questo su Linux chiamato 'wc'.

Appena

wc -l *.c 

e ti dà le linee totali e le linee per ogni file.


3
Hey. 'wc' da solo non cerca i sottodiretti e non filtra le righe vuote, entrambe esplicitamente richieste nella domanda.
Jonathan Hartley,

wcconta le righe vuote. L'OP vuole contare le linee non vuote. È vero che vorrà usare wc, ma solo dopo che è stato modificato in streaming usandosed
EhevuTov
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.