Conteggio delle righe di codice?


24

se voglio contare le righe di codice, la cosa banale è

cat *.c *.h | wc -l

E se avessi diverse sottodirectory?



3
Fuori tema: perché l'inutile cat? wc -l *.c *.hfa la stessa cosa.
Thomas Padron-McCarthy,

5
@ ThomasPadron-McCarthy No, non lo è. Dovresti wc -l *.c *.h | tail -n 1ottenere un output simile.
Gilles 'SO- smetti di essere malvagio' l'

2
Nota che alcune shell (forse anche la maggior parte) moderne (Bash v4, Zsh, probabilmente di più) forniscono un meccanismo ricorsivo-globbing **, quindi avresti potuto usare wc -l **/*.{h,c}qualcosa di simile. Nota che almeno in Bash questa opzione (chiamata globstar) è disattivata per impostazione predefinita. Ma nota anche che in questo caso particolare, cloco SLOCCountè un'opzione molto migliore. (Inoltre, ackpotrebbe essere preferibile findper trovare / elencare facilmente i file sorgente.)
Kyle Strand

5
wc -l conta le righe, non le righe di codice. 7000 righe vuote verranno comunque visualizzate in wc -l ma non conterebbero in una metrica di codice. (anche i commenti di solito non contano)
coteyr

Risposte:


49

Il modo più semplice è utilizzare lo strumento chiamato cloc. Usalo in questo modo:

cloc .

Questo è tutto. :-)


1
-1 perché questo programma non ha alcun modo di riconoscere linee di codice in lingue al di fuori del suo piccolo cervello noioso. Conosce Ada e Pascal e C e C ++ e Java e JavaScript e linguaggi di tipo "enterprise", ma rifiuta di contare lo SLOC solo per estensione di file, ed è quindi completamente inutile per DSL, o anche per le lingue che sembra non conoscere di.
cat

21
@cat Niente è perfetto e nulla può soddisfare tutte le tue esigenze passate e future.
Ho1,

2
Bene, il linguaggio di programmazione che CLOC rifiuta di riconoscere soddisfa davvero tutte le mie richieste passate e future :)
cat

6
@cat secondo la documentazione CLOC che può leggere in un file di definizione della lingua, quindi c'è un modo per farlo riconoscere il codice nelle lingue che non ha definito. Inoltre è open source, quindi puoi sempre estenderlo per renderlo migliore!
Centimane,

39

Probabilmente dovresti usare SLOCCount o cloc per questo, sono progettati specificamente per contare le righe di codice sorgente in un progetto, indipendentemente dalla struttura della directory ecc .; o

sloccount .

o

cloc .

produrrà un rapporto su tutto il codice sorgente a partire dalla directory corrente.

Se vuoi usare finde wc, GNU wcha una bella --files0-fromopzione:

find . -name '*.[ch]' -print0 | wc --files0-from=-

(Grazie a SnakeDoc per il suggerimento cloc !)


+1 per lo sloccount. È interessante notare che l'esecuzione sloccount /tmp/stackexchange(creata di nuovo il 17 maggio dopo il mio riavvio più recente) afferma che il costo stimato per lo sviluppo dei file sh, perl, awk, ecc. Che ha trovato è di $ 11,029. e ciò non include le righe singole che non sono mai state trasformate in un file di script.
Cas

11
Stimare i costi in base a righe di codice? Che dire di tutte le persone impiegate per ricodificare gli spaghetti in qualcosa di sostenibile?
Smetti di fare del male a Monica l'

@OrangeDog potresti sempre provare a tenerne conto nell'overhead; consultare la documentazione per una spiegazione del calcolo (con dati salariali molto vecchi) e i parametri che è possibile modificare.
Stephen Kitt,

5
clocva bene anche: github.com/AlDanial/cloc
SnakeDoc l'

@StephenKitt> ancora, il problema principale è che conta indietro. Quando ripulisci il codice, spesso finisci con meno righe. Sicuramente potresti provare a ondeggiare a mano un overhead per sostenere il resto del codice per tenere conto di quello rimosso, ma non vedo come sia meglio che indovinare l'intero prezzo in primo luogo.
extra il

10

Dato che il wccomando può accettare più argomenti, puoi semplicemente passare tutti i nomi dei file wcusando l' +argomento -execdell'azione di GNU find:

find . -type f -name '*.[ch]' -exec wc -l {} +

In alternativa, in bash, usando l'opzione shell globstarper attraversare ricorsivamente le directory:

shopt -s globstar
wc -l **/*.[ch]

Altre shell attraversano ricorsivamente per impostazione predefinita (ad esempio zsh) o hanno opzioni simili come globstar, beh, almeno la maggior parte.


1
+1 per non aver bisogno di installare software non standard su una macchina in cui non ho root
Bamboomy

5

Puoi usare findinsieme a xargse wc:

find . -type f -name '*.h' -o -name '*.c' | xargs wc -l

2
(presupponendo che i percorsi dei file non contengano spazi vuoti, nuove righe, virgolette singole, virgolette doppie di caratteri barra rovesciata. Può anche generare diverse totalrighe se wcvengono invocati diversi messaggi.)
Stéphane Chazelas

Forse il wcproblema dei vari comandi può essere risolto eseguendo il piping findalla while read FILENAME; do . . .donestruttura. E all'interno del ciclo while usare wc -l. Il resto sta riassumendo le linee totali in una variabile e la sta visualizzando.
Sergiy Kolodyazhnyy,

5

Se ti trovi in ​​un ambiente in cui non hai accesso clocecc, ti suggerirei

find -name '*.[ch]' -type f -exec cat '{}' + | grep -c '[^[:space:]]'

Run-through: findcerca ricorsivamente tutti i file regolari il cui nome termina in uno .co .he viene eseguito catsu di essi. L'output viene reindirizzato grepper contare tutte le righe non vuote (quelle che contengono almeno un carattere non spaziante).


4

Come è stato sottolineato nei commenti, cat file | wc -lè , non equivale a wc -l filequanto gli ex stampe soltanto un numero mentre il secondo stampe un numero e il nome del file. Allo stesso modo cat * | wc -lstamperà solo un numero, mentre wc -l *stamperà una riga di informazioni per ciascun file.

Nello spirito della semplicità, rivisitiamo la domanda effettivamente posta:

se voglio contare le righe di codice, la cosa banale è

cat *.c *.h | wc -l

E se avessi diverse sottodirectory?

In primo luogo, puoi semplificare anche il tuo banale comando per:

cat *.[ch] | wc -l

E infine, l'equivalente di molte sottodirectory è:

find . -name '*.[ch]' -exec cat {} + | wc -l

Questo potrebbe forse essere migliorato in molti modi, ad esempio limitando i file corrispondenti solo ai file regolari (non alle directory) aggiungendo -type f- ma il findcomando dato è l' esatto equivalente ricorsivo di cat *.[ch].


3

Esempio usando awk:

find . -name '*.[ch]' -exec wc -l {} \; |
  awk '{SUM+=$1}; END { print "Total number of lines: " SUM }'

Utilizzare +al posto di \;.
Jonathan Leffler,

@JonathanLeffler Why?
Hastur,

1
@Hastur: funziona wc -lper gruppi di file, un po 'come xargsfa, ma gestisce i caratteri di palla dispari (come gli spazi) nei nomi dei file senza bisogno di xargso (non standard) -print0e delle -0opzioni per finde xargsrispettivamente. È un'ottimizzazione minore. Il rovescio della medaglia sarebbe che ogni invocazione di wcavrebbe generato un conteggio totale di righe alla fine quando dati più file - lo awkscript avrebbe dovuto occuparsene. Quindi, non è una schiacciata, ma molto spesso, usare +al posto di \;con findè una buona idea.
Jonathan Leffler,

@JonathanLeffler Grazie. Sono d'accordo. Le mie preoccupazioni, tuttavia, riguardavano la lunghezza della stringa del parametro passata a wc. Se sconosciuto a priori il numero di file che verranno trovati , esiste il rischio di superare tale limite o in qualche modo viene gestito da find?
Hastur,

2
@Hastur: findraggruppa i file in comodi bundle di dimensioni, che non supereranno il limite di lunghezza per l'elenco degli argomenti sulla piattaforma, consentendo l'ambiente (che esce dalla lunghezza dell'elenco degli argomenti - quindi la lunghezza dell'elenco degli argomenti più il la lunghezza dell'ambiente deve essere inferiore a un valore massimo). IOW, findfa bene il lavoro, come xargsfa bene il lavoro.
Jonathan Leffler,

1

comando semplice:

find . -name '*.[ch]' | xargs wc -l

(presupponendo che i percorsi dei file non contengano spazi vuoti, nuove righe, virgolette singole, virgolette doppie di caratteri barra rovesciata. Può anche generare diverse totalrighe se wcvengono invocati diversi messaggi.)
Stéphane Chazelas

0

Se sei su Linux ti consiglio il mio strumento, poliglotta . È drammaticamente più veloce di cloce più ricco di funzionalità sloccount.

Dovresti essere in grado di compilare anche su BSD, anche se non ci sono file binari forniti.

Puoi invocarlo con

poly .

-2

find . -name \*.[ch] -print | xargs -n 1 wc -ldovrebbe fare il trucco. Ci sono anche diverse possibili variazioni su questo, come usare -execinvece di collegare l'output a wc.


4
Ma find . -name \*.[ch] -printnon stampa il contenuto dei file, solo i nomi dei file. Quindi conto il numero di file invece no? Ho bisogno di `xargs '?
Niklas,

@ Programmer400 sì, ne avresti bisogno xargse dovresti anche cercare più wcinvocazioni se hai molti file; dovresti cercare tutte le totalrighe e sommarle.
Stephen Kitt,

Se vuoi solo il conteggio totale delle righe, dovresti farlofind . -name \*.[ch] -print0 | xargs -0 cat | wc -l
soffice

Nota che this ( find . -name \*.[ch] -print | wc -l) conta il numero di file (a meno che il nome di un file contenga una nuova riga - ma questo è molto insolito) - non conta il numero di righe nei file.
Jonathan Leffler,
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.