Suchen Sie Dateien, die mehrere Schlüsselwörter enthalten, an einer beliebigen Stelle in der Datei

16

Ich suche nach einer Möglichkeit, alle Dateien in einem Verzeichnis aufzulisten, die an einer beliebigen Stelle in der Datei den vollständigen Satz der gesuchten Schlüsselwörter enthalten.

Die Schlüsselwörter müssen also nicht in derselben Zeile stehen.

Ein Weg dies zu tun wäre:

grep -l one $(grep -l two $(grep -l three *))

Drei Schlüsselwörter sind nur ein Beispiel, es können auch zwei oder vier sein und so weiter.

Ein zweiter Weg, den ich mir vorstellen kann, ist:

grep -l one * | xargs grep -l two | xargs grep -l three

Eine dritte Methode, die in einer anderen Frage auftauchte , wäre:

find . -type f \
  -exec grep -q one {} \; -a \
  -exec grep -q two {} \; -a \
  -exec grep -q three {} \; -a -print

Aber das ist definitiv nicht die Richtung, in die ich hier gehe. Ich möchte etwas , das mit weniger Aufwand und möglicherweise nur ein Anruf grep, awk, perloder ähnliches.

Zum Beispiel gefällt mir, wie awkSie Zeilen abgleichen können, die alle Schlüsselwörter enthalten , wie:

awk '/one/ && /two/ && /three/' *

Oder drucken Sie nur die Dateinamen:

awk '/one/ && /two/ && /three/ { print FILENAME ; nextfile }' *

Ich möchte jedoch Dateien suchen, bei denen sich die Schlüsselwörter möglicherweise an einer beliebigen Stelle in der Datei befinden, nicht unbedingt in derselben Zeile.


Bevorzugte Lösungen wären gzip-freundlich, zum Beispiel grepdie zgrepVariante, die bei komprimierten Dateien funktioniert. Warum ich dies erwähne, ist, dass einige Lösungen angesichts dieser Einschränkung möglicherweise nicht gut funktionieren. Im Beispiel zum awkDrucken übereinstimmender Dateien können Sie beispielsweise nicht einfach Folgendes tun:

zcat * | awk '/pattern/ {print FILENAME; nextfile}'

Sie müssen den Befehl in etwa wie folgt ändern:

for f in *; do zcat $f | awk -v F=$f '/pattern/ { print F; nextfile }'; done

Aufgrund der Einschränkung müssen Sie also awkviele Male aufrufen , obwohl Sie dies bei nicht komprimierten Dateien nur einmal tun können. Und natürlich wäre es besser, einfach zawk '/pattern/ {print FILENAME; nextfile}' *den gleichen Effekt zu erzielen. Daher würde ich Lösungen vorziehen, die dies ermöglichen.

arekolek
quelle
1
Sie müssen nicht gzipfreundlich sein, nur zcatdie Dateien zuerst.
Terdon
@terdon Ich habe den Beitrag bearbeitet und erklärt, warum ich erwähne, dass Dateien komprimiert sind.
Arekolek
Es gibt keinen großen Unterschied, ob awk einmal oder mehrmals gestartet wird. Ich meine, OK, ein bisschen Aufwand, aber ich bezweifle, dass Sie den Unterschied überhaupt bemerken würden. Es ist natürlich möglich, awk / perl zu veranlassen, was auch immer das Skript selbst macht, aber das wird zu einem vollständigen Programm und nicht zu einem schnellen Einzeiler. Ist es das was du willst?
terdon
@terdon Persönlich ist der wichtigere Aspekt für mich, wie kompliziert der Befehl sein wird (ich denke, meine zweite Bearbeitung kam, während Sie kommentierten). Zum Beispiel können die grepLösungen einfach angepasst werden, indem man den grepAufrufen ein Präfix voranstellt z. Es ist nicht erforderlich, dass ich auch die Dateinamen bearbeite.
Arekolek
Ja, aber das ist es grep. AFAIK, nur grepund cathaben Standard "Z-Varianten". Ich glaube nicht, dass es einfacher sein wird, als eine for f in *; do zcat -f $f ...Lösung zu verwenden. Alles andere müsste ein vollständiges Programm sein, das vor dem Öffnen die Dateiformate überprüft oder eine Bibliothek verwendet, um dasselbe zu tun.
Terdon

Antworten:

13
awk 'FNR == 1 { f1=f2=f3=0; };

     /one/   { f1++ };
     /two/   { f2++ };
     /three/ { f3++ };

     f1 && f2 && f3 {
       print FILENAME;
       nextfile;
     }' *

Wenn Sie gzippte Dateien automatisch verarbeiten möchten, führen Sie dies entweder in einer Schleife mit zcat(langsam und ineffizient, da Sie awkin einer Schleife mehrmals nacheinander suchen, einmal für jeden Dateinamen) aus oder schreiben Sie denselben Algorithmus neu perlund verwenden Sie das IO::Uncompress::AnyUncompressBibliotheksmodul, das dies kann Dekomprimieren Sie verschiedene Arten von komprimierten Dateien (gzip, zip, bzip2, lzop). oder in Python, das auch Module für den Umgang mit komprimierten Dateien enthält.


In dieser perlVersion können IO::Uncompress::AnyUncompressbeliebig viele Muster und Dateinamen (entweder mit Klartext oder mit komprimiertem Text) eingegeben werden.

Alle vorherigen Argumente --werden als Suchmuster behandelt. Alle nachfolgenden Argumente --werden als Dateinamen behandelt. Primitive, aber effektive Optionsverwaltung für diesen Job. Ein besseres Optionshandling (z. B. um eine -iOption für Suchen ohne Berücksichtigung der Groß- / Kleinschreibung zu unterstützen) könnte mit den Modulen Getopt::Stdoder erreicht werden Getopt::Long.

Führen Sie es so aus:

$ ./arekolek.pl one two three -- *.gz *.txt
1.txt.gz
4.txt.gz
5.txt.gz
1.txt
4.txt
5.txt

(Ich werde keine Dateien auflisten {1..6}.txt.gzund {1..6}.txthier ... sie enthalten nur einige oder alle Wörter "eins" "zwei" "drei" "vier" "fünf" und "sechs" zum Testen. Die in der Ausgabe oben aufgelisteten Dateien Enthalten Sie alle drei Suchmuster. Testen Sie es selbst mit Ihren eigenen Daten.)

#! /usr/bin/perl

use strict;
use warnings;
use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;

my %patterns=();
my @filenames=();
my $fileargs=0;

# all args before '--' are search patterns, all args after '--' are
# filenames
foreach (@ARGV) {
  if ($_ eq '--') { $fileargs++ ; next };

  if ($fileargs) {
    push @filenames, $_;
  } else {
    $patterns{$_}=1;
  };
};

my $pattern=join('|',keys %patterns);
$pattern=qr($pattern);
my $p_string=join('',sort keys %patterns);

foreach my $f (@filenames) {
  #my $lc=0;
  my %s = ();
  my $z = new IO::Uncompress::AnyUncompress($f)
    or die "IO::Uncompress::AnyUncompress failed: $AnyUncompressError\n";

  while ($_ = $z->getline) {
    #last if ($lc++ > 100);
    my @matches=( m/($pattern)/og);
    next unless (@matches);

    map { $s{$_}=1 } @matches;
    my $m_string=join('',sort keys %s);

    if ($m_string eq $p_string) {
      print "$f\n" ;
      last;
    }
  }
}

Ein Hash %patternsenthält den vollständigen Satz von Mustern, die Dateien enthalten müssen. Mindestens eines von jedem Mitglied $_pstringist eine Zeichenfolge, die die sortierten Schlüssel dieses Hash enthält. Die Zeichenfolge $patternenthält einen vorkompilierten regulären Ausdruck, der ebenfalls aus dem %patternsHash erstellt wurde.

$patternwird mit jeder Zeile jeder Eingabedatei verglichen (wobei der /oModifikator nur zum Kompilieren verwendet wird, $patternda bekannt ist, dass er sich während des Laufs niemals ändert) und map()wird verwendet, um einen Hash (% s) zu erstellen, der die Übereinstimmungen für jede Datei enthält.

Wenn alle Muster in der aktuellen Datei angezeigt wurden (indem Sie vergleichen, ob $m_string(die sortierten Eingaben in %s) gleich sind $p_string), drucken Sie den Dateinamen und springen Sie zur nächsten Datei.

Dies ist keine besonders schnelle Lösung, aber nicht unangemessen langsam. Die erste Version benötigte 4 Minuten, um nach drei Wörtern in komprimierten Protokolldateien im Wert von 74 MB zu suchen (insgesamt 937 MB unkomprimiert). Diese aktuelle Version dauert 1m13s. Es könnten wahrscheinlich weitere Optimierungen vorgenommen werden.

Eine offensichtliche Optimierung ist dies in Verbindung mit dieser verwenden xargs‚s -Paka --max-procsmehr Suchen auf Teilmengen der Dateien parallel laufen zu lassen. Dazu müssen Sie die Anzahl der Dateien zählen und durch die Anzahl der Kerne / CPUs / Threads Ihres Systems dividieren (und durch Addieren von 1 aufrunden). Beispiel: In meinem Beispielsatz wurden 269 Dateien durchsucht, und mein System verfügt über 6 Kerne (ein AMD 1090T).

patterns=(one two three)
searchpath='/var/log/apache2/'
cores=6
filecount=$(find "$searchpath" -type f -name 'access.*' | wc -l)
filespercore=$((filecount / cores + 1))

find "$searchpath" -type f -print0 | 
  xargs -0r -n "$filespercore" -P "$cores" ./arekolek.pl "${patterns[@]}" --

Mit dieser Optimierung wurden in nur 23 Sekunden alle 18 übereinstimmenden Dateien gefunden. Dasselbe könnte natürlich mit jeder anderen Lösung geschehen. HINWEIS: Die Reihenfolge der in der Ausgabe aufgelisteten Dateinamen ist unterschiedlich und muss ggf. nachträglich sortiert werden.

Wie von @arekolek festgestellt, können mehrere zgreps mit find -execoder xargswesentlich schneller vorgehen. Dieses Skript bietet jedoch den Vorteil, dass es eine beliebige Anzahl von zu suchenden Mustern unterstützt und mit verschiedenen Arten der Komprimierung umgehen kann.

Wenn sich das Skript darauf beschränkt, nur die ersten 100 Zeilen jeder Datei zu untersuchen, werden alle Zeilen (in meinem 74-MB-Beispiel mit 269 Dateien) in 0,6 Sekunden durchlaufen. Wenn dies in einigen Fällen nützlich ist, kann es zu einer Befehlszeilenoption gemacht werden (z. B. -l 100), aber es besteht das Risiko, dass nicht alle übereinstimmenden Dateien gefunden werden.


Übrigens werden laut Handbuch folgende IO::Uncompress::AnyUncompressKomprimierungsformate unterstützt:


Eine letzte (ich hoffe) Optimierung. Durch die Verwendung des PerlIO::gzipModuls (in debian as gepackt libperlio-gzip-perl) anstelle von konnte IO::Uncompress::AnyUncompressich die Zeit für die Verarbeitung meiner 74 MB großen Protokolldateien auf ca. 3,1 Sekunden reduzieren. Es gab auch einige kleine Verbesserungen durch die Verwendung eines einfachen Hashes anstatt Set::Scalar(was mit der IO::Uncompress::AnyUncompressVersion auch ein paar Sekunden sparte ).

PerlIO::gzipwurde als schnellster Perl-Gunzip in /programming//a/1539271/137158 empfohlen (gefunden mit einer Google-Suche nach perl fast gzip decompress)

Das Verwenden xargs -Pmit diesem hat es überhaupt nicht verbessert. Tatsächlich schien es ihn sogar um 0,1 bis 0,7 Sekunden zu verlangsamen. (Ich habe vier Läufe ausprobiert und mein System erledigt andere Dinge im Hintergrund, die das Timing verändern.)

Der Preis ist, dass diese Version des Skripts nur komprimierte und nicht komprimierte Dateien verarbeiten kann. Geschwindigkeit vs Flexibilität: 3,1 Sekunden für diese Version vs 23 Sekunden für die IO::Uncompress::AnyUncompressVersion mit einem xargs -PWrapper (oder 1m13s ohne xargs -P).

#! /usr/bin/perl

use strict;
use warnings;
use PerlIO::gzip;

my %patterns=();
my @filenames=();
my $fileargs=0;

# all args before '--' are search patterns, all args after '--' are
# filenames
foreach (@ARGV) {
  if ($_ eq '--') { $fileargs++ ; next };

  if ($fileargs) {
    push @filenames, $_;
  } else {
    $patterns{$_}=1;
  };
};

my $pattern=join('|',keys %patterns);
$pattern=qr($pattern);
my $p_string=join('',sort keys %patterns);

foreach my $f (@filenames) {
  open(F, "<:gzip(autopop)", $f) or die "couldn't open $f: $!\n";
  #my $lc=0;
  my %s = ();
  while (<F>) {
    #last if ($lc++ > 100);
    my @matches=(m/($pattern)/ogi);
    next unless (@matches);

    map { $s{$_}=1 } @matches;
    my $m_string=join('',sort keys %s);

    if ($m_string eq $p_string) {
      print "$f\n" ;
      close(F);
      last;
    }
  }
}
cas
quelle
for f in *; do zcat $f | awk -v F=$f '/one/ {a++}; /two/ {b++}; /three/ {c++}; a&&b&&c { print F; nextfile }'; donefunktioniert gut, aber in der Tat dauert 3-mal so lange wie meine grepLösung, und ist eigentlich komplizierter.
Arekolek
1
OTOH, für reine Textdateien wäre es schneller. und der gleiche Algorithmus, der in einer Sprache mit Unterstützung für das Lesen komprimierter Dateien (wie Perl oder Python) implementiert ist, wie ich vorgeschlagen habe, wäre schneller als mehrere greps. "complication" ist zum Teil subjektiv - ich persönlich denke, ein einzelnes awk - oder perl - oder python - Skript ist weniger kompliziert als mehrere greps mit oder ohne find .... @ terdons Antwort ist gut und funktioniert auch ohne das erwähnte Modul (aber auf kosten des forkens von zcat für jede komprimierte datei)
cas
Ich musste apt-get install libset-scalar-perldas Skript verwenden. Aber es scheint nicht in einer angemessenen Zeit zu enden.
Arekolek
Wie viele und wie groß (komprimiert und unkomprimiert) sind die Dateien, nach denen Sie suchen? Dutzende oder Hunderte von kleinen bis mittleren oder Tausende von großen Dateien?
cas
Hier ist ein Histogramm der Größe komprimierter Dateien (20 bis 100 Dateien, bis zu 50 MB, meist jedoch unter 5 MB). Unkomprimiert sehen gleich aus, aber mit Größen multipliziert mit 10.
Arekolek
11

Stellen Sie das Datensatztrennzeichen .so ein, dass awkdie gesamte Datei als eine Zeile behandelt wird:

awk -v RS='.' '/one/&&/two/&&/three/{print FILENAME}' *

Ähnlich mit perl:

perl -ln00e '/one/&&/two/&&/three/ && print $ARGV' *
jimmij
quelle
3
Ordentlich. Beachten Sie, dass dadurch die gesamte Datei in den Speicher geladen wird und dies bei großen Dateien möglicherweise ein Problem darstellt.
Terdon
Ich habe dies zunächst positiv bewertet, weil es vielversprechend aussah. Ich kann es jedoch nicht zum Arbeiten mit komprimierten Dateien bringen. for f in *; do zcat $f | awk -v RS='.' -v F=$f '/one/ && /two/ && /three/ { print F }'; donegibt nichts aus.
Arekolek
@arekolek Diese Schleife funktioniert bei mir. Sind Ihre Dateien richtig komprimiert?
Jimmy
@arekolek benötigen Sie, zcat -f "$f"wenn einige der Dateien nicht komprimiert sind.
Terdon
Ich habe es auch mit nicht komprimierten Dateien getestet und es werden awk -v RS='.' '/bfs/&&/none/&&/rgg/{print FILENAME}' greptest/*.txtimmer noch keine Ergebnisse zurückgegeben, während grep -l rgg $(grep -l none $(grep -l bfs greptest/*.txt))die erwarteten Ergebnisse zurückgegeben werden.
Arekolek
3

Bei komprimierten Dateien können Sie eine Schleife über jede Datei erstellen und diese zuerst dekomprimieren. Mit einer leicht geänderten Version der anderen Antworten können Sie dann Folgendes tun:

for f in *; do 
    zcat -f "$f" | perl -ln00e '/one/&&/two/&&/three/ && exit(0); }{ exit(1)' && 
        printf '%s\n' "$f"
done

Das Perl-Skript wird mit 0Status (Erfolg) beendet, wenn alle drei Zeichenfolgen gefunden wurden. Das }{ist Perl Abkürzung für END{}. Alle folgenden Aktionen werden ausgeführt, nachdem alle Eingaben verarbeitet wurden. Das Skript wird also mit einem Exit-Status ungleich 0 beendet, wenn nicht alle Zeichenfolgen gefunden wurden. Daher && printf '%s\n' "$f"wird der Dateiname nur gedruckt, wenn alle drei gefunden wurden.

Oder, um das Laden der Datei in den Speicher zu vermeiden:

for f in *; do 
    zcat -f "$f" 2>/dev/null | 
        perl -lne '$k++ if /one/; $l++ if /two/; $m++ if /three/;  
                   exit(0) if $k && $l && $m; }{ exit(1)' && 
    printf '%s\n' "$f"
done

Wenn Sie das Ganze wirklich in einem Skript ausführen möchten, können Sie Folgendes tun:

#!/usr/bin/env perl

use strict;
use warnings;

## Get the target strings and file names. The first three
## arguments are assumed to be the strings, the rest are
## taken as target files.
my ($str1, $str2, $str3, @files) = @ARGV;

FILE:foreach my $file (@files) {
    my $fh;
    my ($k,$l,$m)=(0,0,0);
    ## only process regular files
    next unless -f $file ;
    ## Open the file in the right mode
    $file=~/.gz$/ ? open($fh,"-|", "zcat $file") : open($fh, $file);
    ## Read through each line
    while (<$fh>) {
        $k++ if /$str1/;
        $l++ if /$str2/;
        $m++ if /$str3/;
        ## If all 3 have been found
        if ($k && $l && $m){
            ## Print the file name
            print "$file\n";
            ## Move to the net file
            next FILE;
        }
    }
    close($fh);
}

Speichern Sie das obige Skript foo.plirgendwo in Ihrem $PATH, machen Sie es ausführbar und führen Sie es folgendermaßen aus:

foo.pl one two three *
terdon
quelle
2

Von allen bisher vorgeschlagenen Lösungen ist meine ursprüngliche Lösung mit grep die schnellste und dauert 25 Sekunden. Der Nachteil ist, dass das Hinzufügen und Entfernen von Keywords mühsam ist. Also habe ich mir ein Skript ausgedacht (synchronisiert multi), das das Verhalten simuliert, aber erlaubt, die Syntax zu ändern:

#!/bin/bash

# Usage: multi [z]grep PATTERNS -- FILES

command=$1

# first two arguments constitute the first command
command_head="$1 -le '$2'"
shift 2

# arguments before double-dash are keywords to be piped with xargs
while (("$#")) && [ "$1" != -- ] ; do
  command_tail+="| xargs $command -le '$1' "
  shift
done
shift

# remaining arguments are files
eval "$command_head $@ $command_tail"

Das Schreiben multi grep one two three -- *entspricht also meinem ursprünglichen Vorschlag und läuft in der gleichen Zeit ab. Ich kann es auch problemlos für komprimierte Dateien verwenden, indem ich zgrepstattdessen als erstes Argument verwende.

Andere Lösungen

Ich habe auch mit einem Python-Skript experimentiert und dabei zwei Strategien angewendet: zeilenweise Suche nach allen Schlüsselwörtern und stichwortweise Suche in der gesamten Datei. Die zweite Strategie war in meinem Fall schneller. Aber es war langsamer als nur die Verwendung grepund endete in 33 Sekunden. Der zeilenweise Keyword-Abgleich ist in 60 Sekunden abgeschlossen.

#!/usr/bin/python3

import gzip, sys

i = sys.argv.index('--')
patterns = sys.argv[1:i]
files = sys.argv[i+1:]

for f in files:
  with (gzip.open if f.endswith('.gz') else open)(f, 'rt') as s:
    txt = s.read()
    if all(p in txt for p in patterns):
      print(f)

Das Skript von terdon wurde in 54 Sekunden beendet. Eigentlich hat es 39 Sekunden gedauert, weil mein Prozessor Dual-Core ist. Das ist interessant, weil mein Python-Skript 49 Sekunden (und grep29 Sekunden) Wandzeit benötigte .

Das Skript von cas konnte auch bei einer geringeren Anzahl von Dateien, die mit weniger als grep4 Sekunden verarbeitet wurden, nicht in angemessener Zeit beendet werden , sodass ich es beenden musste.

Aber sein ursprünglicher awkVorschlag hat, obwohl er langsamer ist als er grepist, potenzielle Vorteile. In einigen Fällen ist zumindest nach meiner Erfahrung zu erwarten, dass alle Schlüsselwörter irgendwo im Kopf der Datei erscheinen sollten, wenn sie überhaupt in der Datei vorhanden sind. Dies verleiht dieser Lösung eine dramatische Leistungssteigerung:

for f in *; do
  zcat $f | awk -v F=$f \
    'NR>100 {exit} /one/ {a++} /two/ {b++} /three/ {c++} a&&b&&c {print F; exit}'
done

Endet in einer Viertelsekunde im Gegensatz zu 25 Sekunden.

Natürlich haben wir möglicherweise nicht den Vorteil, nach Stichwörtern zu suchen, die bekanntermaßen am Anfang der Dateien vorkommen. In einem solchen Fall NR>100 {exit}dauert die Lösung ohne 63 Sekunden (50 Sekunden Wandzeit).

Nicht komprimierte Dateien

Es gibt keinen signifikanten Unterschied in der Laufzeit zwischen meiner grepLösung und dem awkVorschlag von cas. Die Ausführung dauert jeweils einen Bruchteil einer Sekunde.

Beachten Sie, dass FNR == 1 { f1=f2=f3=0; }in diesem Fall die Variableninitialisierung erforderlich ist, um die Zähler für jede nachfolgende verarbeitete Datei zurückzusetzen. Für diese Lösung muss der Befehl an drei Stellen bearbeitet werden, wenn Sie ein Schlüsselwort ändern oder neue hinzufügen möchten. Auf der anderen Seite können grepSie mit nur | xargs grep -l fourdas gewünschte Schlüsselwort anhängen oder bearbeiten.

Ein Nachteil einer grepLösung, die eine Befehlsersetzung verwendet, besteht darin, dass sie hängen bleibt, wenn vor dem letzten Schritt an einer beliebigen Stelle in der Kette keine übereinstimmenden Dateien vorhanden sind. Dies hat keine Auswirkung auf die xargsVariante, da die Pipe abgebrochen wird, sobald grepein Status ungleich Null zurückgegeben wird. Ich habe mein Skript für die Verwendung aktualisiert, xargsdamit ich nicht selbst damit umgehen muss, wodurch das Skript einfacher wird.

arekolek
quelle
Ihre Python-Lösung kann davon profitieren, dass Sie die Schleife mitnot all(p in text for p in patterns)
iruvar
@iruvar Danke für den Vorschlag. Ich habe es (ohne not) ausprobiert und es war in 32 Sekunden fertig, also nicht viel besser, aber es ist auf jeden Fall besser lesbar.
Arekolek
Sie könnten ein assoziatives Array anstelle von f1, f2, f3 in awk verwenden, mit key = Suchmuster, val = count
cas
@arekolek sehe meine neuste Version PerlIO::gzipeher unter Verwendung als IO::Uncompress::AnyUncompress. Jetzt dauert es nur noch 3,1 Sekunden anstatt 1m13s, um meine 74MB Protokolldateien zu verarbeiten.
cas
Übrigens, wenn Sie zuvor ausgeführt haben eval $(lesspipe)(z. B. in Ihrem .profile, etc), können Sie lessstatt verwenden zcat -fund Ihr forLoop-Wrapper awkwird in der Lage sein, jede Art von Datei zu verarbeiten, die dies lesskann (gzip, bzip2, xz und mehr) .... less kann erkennen, ob stdout eine Pipe ist und gibt nur einen Stream an stdout aus, wenn dies der Fall ist.
cas
0

Eine weitere Option: Geben Sie Wörter nacheinander ein, xargsdamit sie für grepdie Datei ausgeführt werden. xargskann selbst zum Beenden veranlasst werden, sobald ein grepRückgabefehler durch Rücksendung 255an ihn gemeldet wird (siehe xargsDokumentation). Natürlich wird das Laichen von Muscheln und Gabeln, die an dieser Lösung beteiligt sind, diese wahrscheinlich erheblich verlangsamen

printf '%s\n' one two three | xargs -n 1 sh -c 'grep -q $2 $1 || exit 255' _ file

und es zu schleifen

for f in *; do
    if printf '%s\n' one two three | xargs -n 1 sh -c 'grep -q $2 $1 || exit 255' _ "$f"
    then
         printf '%s\n' "$f"
    fi
done
iruvar
quelle
Das sieht gut aus, aber ich bin mir nicht sicher, wie ich das verwenden soll. Was ist _und file? Wird diese Suche in mehreren Dateien als Argument übergeben und gibt Dateien zurück, die alle Schlüsselwörter enthalten?
Arekolek
@arekolek, fügte eine Schleifenversion hinzu. Und was das angeht _, wird es $0an die gespawnte Shell übergeben - dies würde sich als Befehlsname in der Ausgabe von ps- Ich würde mich hier an den Master
wenden