Das Weiterleiten der Ausgabe von „find“ an „xargs wc“ führt zu unsinnigen Gesamtsummen

Das Weiterleiten der Ausgabe von „find“ an „xargs wc“ führt zu unsinnigen Gesamtsummen

In einem Projekt mit Tausenden von Dateien wollte ich die Gesamtzahl der Codezeilen mit den Codezeilen nur in PHP vergleichen (CSS, JavaScript usw. außer Acht lassen).

Wenn ich laufe

find . -type f | xargs wc -l

Die Summe in der letzten Zeile beträgtuntereals wenn ich laufe

find -E . -regex '.+\.(php|inc)' -type f | xargs wc -l

Wenn man bedenkt, dass es sich bei der zweiten findum eine kleinere Dateiliste handeln muss als bei der ersten (und dass es sich dabei um eine strikte Teilmenge davon handelt) find, wie könnte wcim zweiten Fall eine höhere Gesamtsumme gemeldet werden?

Antwort1

xargskann nur passieren ARG_MAXBytes an Argumenten an wc.

Auf meinem Mac ist ARG_MAX kleiner als die vollständigen Dateinamen und relativen Pfade der gesamten Projektdateien.ErsteBefehl, xargsgab die Ergebnisse der findanwc in zwei Chargen, was bedeutete wc, dasszwei Summen, umgeben von Tausenden von Dateinamen. Aber ARG_MAX war zufällig größer als diezweite findAusgabe, so dass der zweite, kleinere Fund alle ineins wcgesamt.

Die Lösung bestand darin, diese Befehle zu verwenden, sodass ich alle Gesamtsummen ohne die (langweiligen) einzelnen Dateizählzeilen sehen konnte:

find . -type f | xargs wc -l | grep total
find -E . -regex '.+\.(php|inc)' -type f | xargs wc -l | grep total

Addieren Sie dann die einzelnen „Gesamt“-Zeilen manuell.

Antwort2

Es gibt viele Möglichkeiten, dies zu tun, und xargses ist nicht die beste. Hier sind ein paar:

  1. Am einfachsten ist es, catjede der gefundenen Dateien durchzuzählen findund die Zeilen zu zählen. Achtung, das funktioniert nur, wenn Ihre Dateinamen keine Leerzeichen oder Sonderzeichen enthalten:

    find . -type f | while read n; do cat $n; done | wc -l
    find -E . -regex '.+\.(php|inc)' -type f | while read n; do cat $n; done | wc -l 
    

    Wenn Ihre Dateinamen wahrscheinlich ungewöhnliche Zeichen (Schrägstriche, Leerzeichen usw.) enthalten, verwenden Sie stattdessen Folgendes:

    find . -type f | while IFS= read -r n; do cat $n; done | wc -l
    find -E . -regex '.+\.(php|inc)' -type f | while IFS= read -r n; do cat $n; done | wc -l 
    
  2. Besser ist es, -execdie Option „find“ zu verwenden:

    find . -name "*.pep" -exec cat {} \; | wc
    find -E . -regex '.+\.(php|inc)' -type f -exec cat {} \; | wc
    

Antwort3

Verwenden Sie es awk, um die verschiedenen „Gesamtzahlen“ der wc -lAusgaben zu summieren!

(Hinweis: wc -lGibt die Anzahl der Zeilenumbruchzeichen zurück, d. h. letzte „Zeilen“ ohne letztes \nZeichen werden nicht gezählt – wie es auch bei awkoder der Fall ist sed.)

export LC_ALL=C
find . -type f -print0 | xargs -0 wc -l | 
    awk '/^ *[[:digit:]]+ total$/{ total+=$1 }END{print total}'


# xargs alternatives using: find ... -exec <wc|awk|sed> ... '{}' +
#man find | less -p '{} \+'

# wc
find . -type f -exec wc -l '{}' + 2>/dev/null | 
   awk '/^ *[[:digit:]]+ total$/{ total+=$1 }END{print total}'

# awk
find . -type f -exec awk 'END {print NR}' '{}' + 2>/dev/null | 
    awk '{ total+=$1 }END{print total}'

# sed
find . -type f -exec sed -n '$=' '{}' + 2>/dev/null | 
    awk '{ total+=$1 }END{print total}'

verwandte Informationen