Piping von einem Fund in grep

8

Was versuche ich zu tun?

Schreiben Sie einen Befehl, der nach Dateien sucht, die von keiner anderen Datei in meinem Projekt benötigt werden.

Was habe ich versucht?

Ich verwende find, um eine Liste von Dateinamen zu erhalten. Jetzt möchte ich die Dateinamen als Suchzeichenfolge verwenden (und nicht die zu durchsuchende Datei).

Ich verwende find server/lib -type f -exec basename {} \; | cut -f 1 -d '.', um meine Liste der Dateinamen abzurufen und die Dateierweiterung zu entfernen.

Jetzt weiß ich, dass grep -R --exclude-dir=node_modules <search-string> . -lich in diesen Dateinamen jeden Dateinamen einfügen möchte, aber ich weiß nicht, wie ich sie als <search-string>Argument übergeben soll.


Andere Information

Ich bin mir auch vage bewusst, dass das grepWeiterleiten an das gesamte Ergebnis der find(der gesamten Liste von Dateien) übergeben werden kann, was ich offensichtlich nicht tun möchte, wenn ich dies tun werde, dann sag es mir.

Auch (obwohl dies wahrscheinlich nicht im Rahmen dieser Frage liegt), da ich dies als eine Möglichkeit verwende, einen der Dateinamen grepzu finden, für die nichts gefunden wird, wäre jeder Ratschlag zum Erhalten dieser Art von Ausgabe sehr dankbar

> <the-command>

filename1
server/lib/foo.js # where these are the list of files in which it appears
test/lib/foo.js

filename2
Not Found! #where `filename2` wasn't found anywhere (obviously)
Simon Legg
quelle

Antworten:

2

Kurze Antwort:

Wenn Sie nur eine Reihe von Zeilen als Argumente an einen anderen Befehl übergeben möchten, xargsist dies Ihr Freund. In diesem Fall möchten Sie das -I {}Flag verwenden , da Sie es in die Mitte eines Befehls stellen . Dies wird {}als Platzhalter festgelegt, sodass Sie ihn überall platzieren können (Sie können Ihren eigenen Platzhalter festlegen, aber ich halte mich normalerweise daran, {}da er nicht mit vielen anderen Dingen verwechselt wird.

Alles zusammenfügen (vorausgesetzt, die Befehle, die Sie gegeben haben, tun das, was Sie denken, dass sie tun!):

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} grep -R --exclude-dir=node_modules {} . -l

Lange Antwort

Ok, also können wir das wahrscheinlich weiter verfolgen. Angenommen , Sie haben das Format wollten Sie bereits erwähnt - man kann xargszu sh -cso können Sie Ketten Befehle:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l"

Wenn Sie dies auf meinem Computer ausführen, erhalten Sie anscheinend die Dateien, in denen sich die Datei befindet . Mein Gehirn ist müde. Anstatt es in ein nettes Skript zu packen (was Sie eigentlich tun sollten, wenn Oneliner knorrig werden und https://www.shellcheck.net/ verwenden, während Sie gerade dabei sind), können Sie dies tun Habe stattdessen diesen schrecklichen Hack, der dir (glaube ich) die Ausgabe gibt, nach der du suchst:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l && printf \"\n\" || printf \"Not found\n\n\""

Spitze
quelle
Vielen Dank, ja, xargs -I {}das habe ich gesucht.
Simon Legg
6

Mit zsh:

projects=(server/lib/**/*(D.:t:r))
grep -rFl --exclude-dir=node_modules -e${(u)^projects} .
  • **/rekursives Globbing. Ein Feature, zshdas Anfang der 90er Jahre eingeführt wurde.
  • (D.:t:r)ist ein Glob-Qualifizierer, eine zshspezifische Funktion, mit der Sie Dateien mit anderen Attributen als dem Namen auswählen oder die Sortierung ändern oder Änderungen an den gefundenen Dateien vornehmen können.
  • D: Punktdateien einschließen und Punktverzeichnisse wie gewohnt durchlaufen find. Höchstwahrscheinlich möchten Sie diesen ausziehen.
  • .: nur reguläre Dateien (wie -type fin find)
  • :t, :r: Verlaufsmodifikatoren wie in csh/, bashaber hier auf die Globbed-Dateien angewendet. :tfür den Schwanz (Basisname), :rfür den Stammnamen (Erweiterung entfernt).
  • x${^array}verteilt die Elemente wie rc's x^$arrayoder fish' s x$array. Zum Beispiel wenn $arrayis ( 1, 2). Das wird x1 x2.
  • ${(u)array}uEntfernen Sie (für Nique) Duplikate ( (u)ein Parametererweiterungsflag).

Für die Liste der Dateien , die enthalten keine der Saiten, ersetzen -lmit -L(GNU vorausgesetzt grep, aber Sie sind bereits GNU-spezifische Optionen hier verwendet wird ). -Fist für die Suche nach festen Zeichenfolgen vorgesehen (da Sie wahrscheinlich nicht möchten, dass diese Projektnamen als reguläre Ausdrücke behandelt werden). Möglicherweise möchten Sie auch eine -wOption grepfür die Wortübereinstimmung einfügen, damit foodiese beispielsweise nicht übereinstimmt foobar(würde aber trotzdem übereinstimmen foo-bar).

Stéphane Chazelas
quelle
Vielen Dank für diese und die Erklärungen, ich war mir nicht bewusst, dass ich so projects=(server/lib/**/*(D.:t:r))ein Array in zsh produziere. Jetzt muss ich jedoch die Dateien grepauflisten, in denen nichts gefunden wurde. Ich denke, ich müsste einen 0 / falschen Exit-Code abfangen?
Simon Legg
@ Simon, siehe den Teil über -Lam Ende der Antwort
Stéphane Chazelas
Ja, das habe ich gesehen. -lsagt mir, wo das Suchergebnis war und -Lwo es nicht gefunden wurde. Aber ich möchte eine Liste der Suchbegriffe wissen , die nirgendwo gefunden wurden und nicht dort, wo sie gefunden wurden / wurden
Simon Legg