Frage

    

Diese Frage bereits eine Antwort hier:

         

Angenommen, ich die Codezeilen in einem Projekt zählen will. Wenn alle Dateien im selben Verzeichnis sind, kann ich ausführen:

cat * | wc -l

Wenn es jedoch Unterverzeichnisse sind, das funktioniert nicht. Für diese Katze arbeiten würde eine rekursive Modus haben müssen. Ich vermute, dies könnte ein Job für xargs sein, aber ich frage mich, ob es eine elegantere Lösung?

War es hilfreich?

Lösung

Zuerst müssen Sie nicht cat verwenden, um Linien zu zählen. Dies ist ein Antipattern Useless Verwendung von Cat (UUoC) genannt. Um Zeilen in Dateien im aktuellen Verzeichnis zu zählen, verwenden Sie wc :

wc -l * 

Dann wird der find Befehl recurses die Unterverzeichnisse:

find . -name "*.c" -exec wc -l {} \;
  • . ist der Name des obersten Verzeichnisses der Suche starten von

  • -name "*.c" ist das Muster der Datei, die Sie interessiert sind,

  • -exec gibt ein Kommando ausgeführt werden

  • {} wird das Ergebnis des Fundes Befehls an den Befehl übergeben werden (hier wc-l)

  • \; zeigt das Ende des Befehls

Mit diesem Befehl wird eine Liste aller Dateien mit ihrer Zeilenzahl gefunden, wenn Sie die Summe für haben wollen alle die Dateien gefunden hat, können Sie verwenden, finden Sie die Dateien zur Liste (mit der -print Option ) und als xargs verwendet diese Liste als Argument wc-l zu übergeben.

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

EDIT Adresse Robert Gamble Kommentar (Danke): (!), Wenn Sie Leerzeichen oder Zeilenumbrüche haben in Dateinamen, dann müssen Sie -print0 Option statt -print und xargs -null so dass die Liste der Dateinamen mit Null- ausgetauscht werden, verwenden terminierten Strings.

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

Die Unix-Philosophie ist es, Werkzeuge zu haben, die nur eine Sache zu tun, und tun es auch.

Andere Tipps

Wenn Sie eine Code-Golf-Antwort:

grep '' -R . | wc -l 

Das Problem mit nur mit wc -l auf seinem eigenen ist es kippt gut absteigen und die oneliners mit

find . -exec wc -l {} \;

Wollen Sie nicht eine Gesamtzeilenzahl geben, weil es wc einmal ausgeführt wird für jede Datei, (Lol!) und

find . -exec wc -l {} + 

Wird verwirrt, sobald der Suche nach den ~ 200k Hits 1 2 Zeichen Argument Grenze für Parameter und stattdessen Anrufe WC mehrere mal, nur jedes Mal, wenn Sie eine kurze Zusammenfassung geben.

Darüber hinaus wird der oben grep Trick nicht mehr als 1 Zeile mit dem Ausgang hinzufügen, wenn es eine binäre Datei trifft, die circumstantially von Nutzen sein könnte.

Für die Kosten von 1 zusätzlichen Befehlszeichen, können Sie binäre Dateien ignorieren vollständig:

 grep '' -IR . | wc -l

Wenn Sie zu Strichzahlen auf binäre Dateien ausführen

 grep '' -aR . | wc -l 
Fußnote auf Grenzen:

Die Dokumente sind ein bisschen vage, ob es eine string Größenbegrenzung oder eine Anzahl von Token Limit.

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

Das bedeutet, seine zu Brocken geht sehr, sehr leicht.

Ich glaube, Sie wahrscheinlich sitzen fest mit xargs

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

chromakode 's Methode gibt das gleiche Ergebnis ist aber viel viel langsamer. Wenn Sie xargs Ihre Katze ing und wc ing kann, sobald starten finden beginnt zu finden.

Gute Erklärung unter Linux: xargs vs. exec {}

Versuchen Sie, den find Befehl, die Verzeichnisse standardmäßig recurses:

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

Der richtige Weg ist:

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

Sie müssen verwenden -print0 weil es nur zwei ungültige Zeichen in Unix-Dateinamen sind: Der Null-Byte und „/“ (Schrägstrich). So zum Beispiel "xxx \ npasswd" ist ein gültiger Name. In Wirklichkeit sind Sie eher Namen mit Leerzeichen in ihnen zu begegnen, though. Die Befehle oben würden jedes Wort als eine separate Datei zählen.

Sie mögen vielleicht auch „-Typ f“ statt -name verwenden, um die Suche auf Dateien zu beschränken.

Mit Katze oder grep in den oben genannten Lösungen ist verschwenderisch, wenn Sie relativ neue GNU-Tools verwenden können, einschließlich Bash:

wc -l --files0-from=<(find . -name \*.c -print0)

Diese Griffe Dateinamen mit Leerzeichen, willkürliche Rekursion und eine beliebige Anzahl von passenden Dateien, auch wenn sie über die Befehlszeile Längengrenze überschreiten.

Ich mag bedienen und Kopf zusammen für eine "rekursiv cat" auf alle Dateien in einem Projektverzeichnis, zum Beispiel:

find . -name "*rb" -print0 | xargs -0 head -10000

Der Vorteil ist, dass der Kopf wird fügen Sie Ihren Dateiname und Pfad:

==> ./recipes/default.rb <==
DOWNLOAD_DIR = '/tmp/downloads'
MYSQL_DOWNLOAD_URL = 'http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.10-debian6.0-x86_64.deb'
MYSQL_DOWNLOAD_FILE = "#{DOWNLOAD_DIR}/mysql-5.6.10-debian6.0-x86_64.deb"

package "mysql-server-5.5"
...

==> ./templates/default/my.cnf.erb <==
#
# The MySQL database server configuration file.
#
...

==> ./templates/default/mysql56.sh.erb <==
PATH=/opt/mysql/server-5.6/bin:$PATH 

Für das komplette Beispiel hier, bitte meine Blog-Post sehen:

http: // haildata .net / 2013/04 / mit-cat-rekursiv mit-schön-formatierten Ausgabe inklusive-Header /

Hinweis: Früher habe ich ‚Kopf -10000‘, klar, wenn ich Dateien über 10.000 Zeilen dies die Ausgabe gestutzt wird ... aber konnte ich den Kopf 100000 aber für „informelle Projekt / Verzeichnissuche“ dieser Ansatz funktioniert sehr gut für mich.

Wenn Sie nur eine Gesamtzeilenzahl generieren möchten und keine Zeile zählen für jede Datei so etwas wie:

find . -type f -exec wc -l {} \; | awk '{total += $1} END{print total}'

funktioniert gut. Dies erspart Ihnen die Notwendigkeit, weitere Text-Filterung in einem Skript zu tun.

wc -cl `find . -name "*.php" -type f`

Hier ist ein Bash-Skript, das die Codezeilen in einem Projekt zählt. Es durchläuft einen Quellbaum rekursiv, und es schließt Leerzeilen und einzeilige Kommentare, die „//".

# $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`
    total=$(($total + $numLines))
    echo "  " $numLines $file
  done
  echo "  " $total in total
}

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

Hier ist, was die Ausgabe wie folgt aussieht für mein Projekt :

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

Viel Spaß! - Curran

find . -name "*.h" -print | xargs wc -l
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top