Anzahl der Dateien, die keine angegebene Zeichenfolge enthalten

7

Ich habe die Frage gelesen , wie man die Anzahl der Dateien herausfindet, die eine bestimmte Zeichenfolge enthalten. Dies ist möglich mit grep -l "string" * | wc -l.

Ist es möglich, dies zu invertieren, indem die Anzahl der Dateien ermittelt wird , die die Zielzeichenfolge nicht enthalten? Ich habe versucht, die -vOption hinzuzufügen , aber dies scheint nicht das richtige Ergebnis zu liefern.

Aldorado
quelle

Antworten:

10

Mit GNU oder OpenBSD grep:

grep -L "string" ./* | grep -c /
UVV
quelle
9

Ein anderer POSIX-Weg:

c=0
for f in *; do
  [ -d "$f" ] && continue
  { grep -q string || c=$(($c + 1)); } < "$f"
done
echo "$c"

Durch Umleiten der Befehlsgruppe anstelle von grepallein wird vermieden, dass Dateien, die wir nicht öffnen können, als 1 gezählt werden (z. B. Dateien, für die wir keine Leseberechtigung haben oder *die sich im aktuellen Verzeichnis nicht versteckt befinden).

Mit GNU grepwäre das Äquivalent:

grep -d skip -L foo ./* | grep -c /

Beachten Sie, dass Sie nicht verwenden können, wc -lda Dateinamen aus mehreren Zeilen bestehen können. Mit ./vermeidet auch Probleme mit Dateinamen , die mit beginnen -oder sind - (das --Umgehen nicht). Beachten Sie, dass Punktdateien ignoriert werden.

Stéphane Chazelas
quelle
4

Hier ist eine POSIX-kompatible Methode, falls Sie keine haben grep -L:

for file in *; do
    awk '/string/ { found=1; exit } END{ if(!found) { printf "x" } }' < "$file"
done | wc -c
Chris Down
quelle
1

Ein anderer POSIX-Weg, der nur grepund verwendet wc:

COUNT_FILES=0
for i in *;do COUNT_FILES=$((COUNT_FILES+1));done
MATCHES=$(grep -l "string" * | wc -l)
NON_MATCHES=$((COUNT_FILES - MATCHES))
echo "There are $NON_MATCHES files not matching \"string\""
Joseph R.
quelle
Beachten Sie, dass 1 zurückgegeben wird, wenn sich im aktuellen Verzeichnis keine nicht versteckte Datei befindet. Möglicherweise möchten Sie auch Verzeichnisse überspringen. Eine andere Möglichkeit, die Dateien zu zählen und eine Race-Bedingung zu vermeiden, wäre die set -- *Verwendung $#und Schleife mit for i do .... Sie können wc -lDateien nicht zählen, da Dateinamen aus mehreren Zeilen bestehen können.
Stéphane Chazelas
0

Je nachdem, wie viele Dateien Sie durchsuchen möchten, ist es ein guter Rat, sich ack-grep anzusehen . Der Grund dafür ist, dass ack-grepes viel schneller als good'ol ist grepund die CLI nahezu identisch ist.

ack-grep -Lur "some string" * | wc -l

klingt.net
quelle
0

Mit zsh:

( arr=(./*(.N^e_'grep -q PATTERN $REPLY'_)); print ${#arr}; )

Dadurch werden die Namen der Dateien, die nicht PATTERNin einem Array enthalten sind, gespeichert und die Anzahl der Elemente im Array zurückgegeben. Es werden Glob-Qualifizierer verwendet : .Wählt nur reguläre Dateien aus (Hinzufügen D, um versteckte Dateien einzuschließen), wird Naktiviert null globund die Zeichenfolge negated ( ^) e: ^e_'grep -q PATTERN $REPLY'_hebt die Auswahl der Dateinamen auf, für die der Shell-Code zwischen den Anführungszeichen zurückgegeben wird true.

don_crissti
quelle