Codezeilen zählen?

24

Wenn ich die Codezeilen zählen will, ist das Triviale

cat *.c *.h | wc -l

Was aber, wenn ich mehrere Unterverzeichnisse habe?

Niklas Rosencrantz
quelle
3
Off-Topic: Warum das Unnötige cat? wc -l *.c *.hmacht das gleiche.
Thomas Padron-McCarthy
5
@ ThomasPadron-McCarthy Nein, tut es nicht. Sie müssten wc -l *.c *.h | tail -n 1eine ähnliche Ausgabe erhalten.
Gilles 'SO- hör auf böse zu sein'
2
Beachten Sie, dass einige (möglicherweise sogar die meisten) modernen Shells (Bash v4, Zsh, wahrscheinlich mehr) einen rekursiven Globbing-Mechanismus verwenden **, so dass Sie möglicherweise wc -l **/*.{h,c}etwas Ähnliches verwendet haben. Beachten Sie, dass in Bash, zumindest diese Option (genannt globstar) ist aus der Standardeinstellung. Beachten Sie aber auch, dass in diesem speziellen Fall clocoder SLOCCounteine viel bessere Option ist. (Auch ackkann findzum einfachen Auffinden / Auflisten von Quelldateien vorzuziehen sein .)
Kyle Strand
5
wc -l zählt Zeilen, keine Codezeilen. In wc -l werden immer noch 7000 Leerzeilen angezeigt, die in einer Codemetrik jedoch nicht gezählt werden. (Kommentare auch in der Regel nicht zählen)
Coteyr

Antworten:

49

Am einfachsten ist es, das aufgerufene Tool zu verwenden cloc. Verwenden Sie es so:

cloc .

Das ist es. :-)

Ho1
quelle
1
-1 weil dieses Programm keine Möglichkeit hat, Codezeilen in Sprachen außerhalb seines kleinen, langweiligen Gehirns zu erkennen. Es kennt sich mit Ada und Pascal und C und C ++ sowie Java und JavaScript und "Enterprise" -Sprachen aus, aber es lehnt es ab, den SLOC nur anhand der Dateierweiterung zu zählen, und ist daher für DSLs oder sogar für Sprachen, die es zufällig nicht kennt, völlig nutzlos Über.
Katze
21
@cat Nichts ist perfekt und nichts kann all Ihre früheren und zukünftigen Anforderungen erfüllen.
Ho1
2
Nun, die Programmiersprache, die CLOC nicht anerkennt, erfüllt tatsächlich alle meine früheren und zukünftigen Anforderungen :)
cat
6
@cat kann laut CLOC-Dokumentation in einer Sprachdefinitionsdatei gelesen werden, sodass es eine Möglichkeit gibt, Code in Sprachen zu erkennen, die es nicht definiert hat. Außerdem ist es Open Source, sodass Sie es jederzeit erweitern können, um es besser zu machen!
Centimane
39

Verwenden Sie hierfür wahrscheinlich SLOCCount oder cloc . Sie wurden speziell zum Zählen von Quellcodezeilen in einem Projekt entwickelt, unabhängig von der Verzeichnisstruktur usw .; entweder

sloccount .

oder

cloc .

erstellt ausgehend vom aktuellen Verzeichnis einen Bericht über den gesamten Quellcode.

Wenn Sie verwenden möchten , findund wc, GNU wchat eine schöne --files0-fromOption:

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

(Danke an SnakeDoc für den Cloc-Vorschlag !)

Stephen Kitt
quelle
+1 für sloccount. Interessanterweise gibt das Ausführen sloccount /tmp/stackexchange(das am 17. Mai nach meinem letzten Neustart erneut erstellt wurde) an, dass die geschätzten Kosten für die Entwicklung der gefundenen sh-, perl-, awk- usw. -Dateien 11.029 US-Dollar betragen. und das schließt nicht die Einzeiler ein, die es nie in eine Skriptdatei geschafft haben.
cas
11
Schätzung der Kosten anhand der Codezeilen? Was ist mit all den Leuten, die beschäftigt sind, um Spaghetti in etwas Wartbares umzuwandeln?
Hören Sie auf, Monica am
@OrangeDog du könntest immer versuchen, das im Overhead zu berücksichtigen; In der Dokumentation finden Sie eine Erläuterung der Berechnung (mit sehr alten Gehaltsdaten) und der Parameter, die Sie anpassen können.
Stephen Kitt
5
clocist auch gut: github.com/AlDanial/cloc
SnakeDoc
@StephenKitt> Trotzdem geht es hauptsächlich darum, rückwärts zu zählen. Beim Bereinigen von Code werden häufig weniger Zeilen angezeigt. Sicher, Sie könnten versuchen, einen Overhead von Hand zu veranlassen, um den Rest des Codes zu verarbeiten, um den entfernten zu berücksichtigen, aber ich sehe nicht, wie es besser ist, als zunächst den gesamten Preis zu erraten.
Spectras
10

Da der wcBefehl mehrere Argumente annehmen kann, können Sie einfach alle Dateinamen an wcdas +Argument der -execAktion von GNU übergeben find:

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

Alternativ können Sie in bashmithilfe der Shell-Option globstardie Verzeichnisse rekursiv durchlaufen:

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

Andere Shells werden standardmäßig rekursiv durchlaufen (z. B. zsh) oder haben ähnliche Optionen wie globstarzumindest die meisten.

heemayl
quelle
1
+1, weil ich keine nicht standardmäßige Software auf einem Computer installieren muss, auf dem ich kein Root-
Verzeichnis
5

Sie können findzusammen mit xargsund verwenden wc:

find . -type f -name '*.h' -o -name '*.c' | xargs wc -l
Kaffeebecher
quelle
2
(Dies setzt voraus, dass die Dateipfade keine Leerzeichen, Zeilenumbrüche, einfache Anführungszeichen und doppelte Anführungszeichen für Backslash-Zeichen enthalten. Es können auch mehrere totalZeilen ausgegeben werden, wenn mehrere wcs aufgerufen werden.)
Stéphane Chazelas
Möglicherweise kann das wcProblem mit mehreren Befehlen durch Weiterleiten findan die while read FILENAME; do . . .doneStruktur behoben werden. Und innerhalb der while-Schleife verwenden wc -l. Der Rest fasst die Gesamtzeilen zu einer Variablen zusammen und zeigt sie an.
Sergiy Kolodyazhnyy
5

Wenn Sie sich in einer Umgebung befinden, in der Sie keinen Zugriff auf clocusw. haben, würde ich vorschlagen

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

Durchlauf: findSucht rekursiv nach allen regulären Dateien, deren Name auf .coder endet .hund catauf denen sie ausgeführt werden. Die Ausgabe wird durchgeleitet, grepum alle nicht leeren Zeilen zu zählen (die, die mindestens ein Zeichen ohne Abstand enthalten).

Kotte
quelle
4

Wie bereits in den Kommentaren erwähnt, cat file | wc -list dies nicht gleichbedeutend damit, wc -l filedass ersteres nur eine Zahl ausgibt, während letzteres eine Zahl und den Dateinamen ausgibt. Ebenso cat * | wc -lwird nur eine Zahl ausgegeben, während wc -l *für jede Datei eine Informationszeile ausgegeben wird.

Lassen Sie uns im Geiste der Einfachheit die tatsächlich gestellte Frage nochmals betrachten:

Wenn ich die Codezeilen zählen will, ist das Triviale

cat *.c *.h | wc -l

Was aber, wenn ich mehrere Unterverzeichnisse habe?

Erstens können Sie sogar Ihren einfachen Befehl vereinfachen, um:

cat *.[ch] | wc -l

Und schließlich ist das Äquivalent für viele Unterverzeichnisse:

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

Dies könnte möglicherweise auf viele Arten verbessert werden, z. B. indem die übereinstimmenden Dateien durch Hinzufügen auf normale Dateien (nicht auf Verzeichnisse) beschränkt werden. -type fDer angegebene findBefehl ist jedoch das genaue rekursive Äquivalent zu cat *.[ch].

Platzhalter
quelle
3

Probe mit awk:

find . -name '*.[ch]' -exec wc -l {} \; |
  awk '{SUM+=$1}; END { print "Total number of lines: " SUM }'
Lambert
quelle
Verwenden Sie +anstelle von \;.
Jonathan Leffler
@ JonathanLeffler Warum?
Hastur
1
@Hastur: Es läuft wc -lfür Gruppen von Dateien, eher wie der xargsFall ist, aber es Griffe odd-Ball - Zeichen (wie Leerzeichen) in Dateinamen ohne entweder zu benötigen xargsoder den (Nicht-Standard) -print0und -0Optionen findund xargsjeweils. Es ist eine kleine Optimierung. Der Nachteil wäre, dass jeder Aufruf von wcam Ende eine Gesamtzeilenzahl ausgibt, wenn mehrere Dateien angegeben werden - das awkSkript hätte sich damit befasst. Es ist also kein Slam-Dunk, aber sehr oft ist es eine gute Idee , +anstelle von \;with zu verwenden find.
Jonathan Leffler
@ JonathanLeffler Vielen Dank. Genau. Meine Bedenken betrafen jedoch die Länge der Parameterzeichenfolge, an die übergeben wurde wc. Wenn die Anzahl der gefundenen Dateien a priori nicht bekannt ist , besteht das Risiko, dass diese Grenze überschritten wird, oder wird sie irgendwie von find verarbeitet?
Hastur
2
@Hastur: findgruppiert die Dateien in Bündel mit praktischer Größe, wobei die Längenbeschränkung für die Argumentliste auf der Plattform nicht überschritten wird, wobei die Umgebung (die sich aus der Länge der Argumentliste ergibt - also die Länge der Argumentliste plus die Länge der Argumentliste) berücksichtigt wird Länge der Umgebung muss kleiner als ein Maximalwert sein). IOW, findmacht den Job richtig, wie xargsmacht der Job richtig.
Jonathan Leffler
1

einfacher Befehl:

find . -name '*.[ch]' | xargs wc -l
malyy
quelle
(Dies setzt voraus, dass die Dateipfade keine Leerzeichen, Zeilenumbrüche, einfache Anführungszeichen und doppelte Anführungszeichen für Backslash-Zeichen enthalten. Es können auch mehrere totalZeilen ausgegeben werden, wenn mehrere wcs aufgerufen werden.)
Stéphane Chazelas
0

Wenn Sie unter Linux arbeiten, empfehle ich mein eigenes Tool, polyglot . Es ist dramatisch schneller als clocund featureful als sloccount.

Sie sollten auch in der Lage sein, auf BSD aufzubauen, obwohl es keine bereitgestellten Binärdateien gibt.

Sie können es mit aufrufen

poly .

quelle
-2

find . -name \*.[ch] -print | xargs -n 1 wc -lsollte den Trick machen. Auch hier gibt es verschiedene Variationsmöglichkeiten, z. B. die Verwendung von -execanstelle der Weiterleitung der Ausgabe an wc.

John
quelle
4
Druckt find . -name \*.[ch] -printaber nicht den Inhalt der Dateien, sondern nur die Dateinamen. Also zähle ich stattdessen die Anzahl der Dateien, oder? Benötige ich "Xargs"?
Niklas Rosencrantz
@ Programmer400 Ja, das würden Sie brauchen xargs, und Sie müssten auch auf mehrere wcAufrufe achten, wenn Sie viele Dateien haben. Sie müssten nach allen totalZeilen suchen und sie summieren.
Stephen Kitt
Wenn Sie nur die Gesamtanzahl der Zeilen anzeigen möchten, müssen Sie dies tunfind . -name \*.[ch] -print0 | xargs -0 cat | wc -l
flauschiger
Beachten Sie, dass this ( find . -name \*.[ch] -print | wc -l) die Anzahl der Dateien zählt (es sei denn, ein Dateiname enthält eine neue Zeile - dies ist jedoch sehr ungewöhnlich) - es zählt nicht die Anzahl der Zeilen in den Dateien.
Jonathan Leffler