Suchen Sie mit pdfgrep nach string in pdf und geben Sie nur den Dateinamen aus

1069
FXux

Ich benutze pdfgrep, um einen Namen in einem pdf zu suchen:

pdfgrep -H 'Fatima Alves' RE/* 

Dieser Befehl gibt den Dateinamen und den Namen aus:

RE/2011-01-RE_60822079000168_23022016_153923(1).PDF: Fatima Alves  RE/2011-01-RE_60822079000168_23022016_153923 (2).PDF: Fatima Alves 

Ich möchte aber nur den Dateinamen drucken, ohne das : Fatima Alves

Ich möchte eine Pipe mit xargs verwenden, um die Matche-Dateien zu verschieben:

pdfgrep -H 'Fatima Alves' RE/* | xargs -I{} mv -i {} ./destination 

In der aktuellen Situation funktioniert die Verschiebung jedoch nicht, da versucht wird, eine Datei zu verschieben, die nicht vorhanden ist:

mv: cannot stat ‘RE/2011-01-RE_60822079000168_23022016_153923(1).PDF: Fatima Alves’: No such file or directory mv: cannot stat ‘RE/2011-01-RE_60822079000168_23022016_153923 (2).PDF: Fatima Alves’: No such file or directory 

Vielen Dank.

-2
-H druckt die Dateinamen und die: Fatima Alves im Finale. FXux vor 8 Jahren 0

2 Antworten auf die Frage

0
l0b0

Sie können die pdfgrepAusgabe wie folgt modifizieren, um sie in verwendbar zu machen xargs:

$ echo 'RE/2011-01-RE_60822079000168_23022016_153923(1).PDF: Fatima Alves' | grep --perl-regexp --only-matching '.*(?=: Fatima Alves$)' RE/2011-01-RE_60822079000168_23022016_153923(1).PDF 

pdfgrepSie können also für jeden regulären Ausdruck und jede Ausgabe Folgendes tun:

regex='Fatima Alves' pdfgrep -H "$regex" RE/* | grep --perl-regexp --only-matching ".*(?=: $regex\$)" 

Bearbeiten:

Ich dachte ursprünglich, dass nur der passende Teil der Zeile von gedruckt wurde pdfgrep. Da die gesamte Zeile gedruckt wird, müssen Sie einfach alles entfernen, einschließlich des Doppelpunkt-Trennzeichens :

pdfgrep -H "$regex" RE/* | sed 's/:.*//' 
PDF ist binär, ich kann nicht nur grep verwenden, ich brauche pdfgrep: / FXux vor 8 Jahren 0
Zur Klarstellung aktualisiert. l0b0 vor 8 Jahren 1
Hei @ l0b0, vielen Dank für die Antwort! Ich bin schwer mit Überprüfen Sie die Ausgabe: http://i.imgur.com/qxYHDP8.png FXux vor 8 Jahren 0
Wir sind fast da, das ist die Ausgabe: http://i.imgur.com/moNYxG2.png Der Fehler "mv: can stat" tritt auf, weil der Name Leerzeichen enthält, oder? Hinzufügen von -0 zu xargs: | xargs -0 löst (wenn ich recht habe), jetzt haben wir ein letztes Problem, der Befehl steckt in der ersten Datei, wie eine Endlosschleife, weißt du warum? FXux vor 8 Jahren 0
@ FátimaAlves Nein, wahrscheinlich gibt es die Fehler, weil einige Dateien schon einmal verschoben wurden. Die Ausgabe von "pdfgrep" sollte bereits sortiert sein, da höchstwahrscheinlich Dateien in der gleichen Reihenfolge verarbeitet werden, in der sich der Globus "RE / *" befindet. Wenn Sie die Ausgabe zuerst an "uniq" übergeben, sollten Sie Folgendes tun: "pdfgrep -H" $ Regex "RE / * | grep --perl-regexp --onlymatching ". * (? =: $ regex \ $)" | uniq | [...] `. @ l0b0, ich würde die `sed`-Lösung entmutigen, da Dateinamen, die Doppelpunkte enthalten, in * nix erlaubt sind. kos vor 8 Jahren 0
@kos Solange es keine Möglichkeit gibt, zu wissen, ob ein Doppelpunkt ein Teil des Dateinamens ist, können Sie nicht zuverlässig eine 100% ige Lösung für dieses Problem erhalten. Ich gehe also zu einer 99% igen Lösung. Und Sie sollten "-u" sortieren, falls "pdfgrep" aus irgendeinem Grund Zeilen in einer verstümmelten Reihenfolge ausgeben kann. l0b0 vor 8 Jahren 0
Die "grep" -Lösung ist eigentlich 100% sicher. Und tatsächlich kann man mit `sed` auch eine 100% sichere Lösung haben:` pdfgrep -H "$ regex" RE / * | sed 's / \ (. * \):. * / \ 1 /' `. kos vor 8 Jahren 0
Arbeitet Jungs !!!! Vielen Dank!!! FXux vor 8 Jahren 0
@kos, können wir diese Regex nicht ändern, um alles bis zum letzten zu vermeiden: ?? Ich versuche es wie Javascript (mit? -Zeichen): sed's s \ (. *? \):. * / \ 1 / 'funktioniert aber nicht. FXux vor 8 Jahren 0
@ FátimaAlves Ich verstehe nicht, was Sie genau tun wollen. "Alles vermeiden bis zum letzten": "wie in" Alles verwerfen bis zum letzten ":" "(dh es wird nur gedruckt, was hinter dem letzten": "steht)? kos vor 8 Jahren 0
Ops, sorry .. ich meine "alles bis zum ersten passen:" hahahaha FXux vor 8 Jahren 0
In der aktuellen Situation stimmt der Regex mit allem bis zum letzten überein: Irgendwann brauche ich Dokumente mit einer Stunde, wie 22:00:00 Uhr, das wäre ein Problem. FXux vor 8 Jahren 0
@ FátimaAlves: Wenn Sie "hahahaha" sagen, scheint es, als würden Sie Witze machen und nicht ernsthaft eine Antwort auf Ihre Frage bekommen. Wenn die Leute das glauben, haben sie das Gefühl, dass Sie unsere Zeit verschwenden, und sie möchten Ihnen möglicherweise nicht mehr helfen. Scott vor 8 Jahren 0
Vielen Dank für den wirklich guten Tipp, Professor .. HAHAHAHAHAHAHAHAHAH FXux vor 8 Jahren 0
0
evadeflow

Ich finde es am einfachsten, den Befehl schrittweise aufzubauen. Sie können die Liste der übereinstimmenden Dateinamen abrufen mit:

$ pdfgrep -i "Fatima Alves" *.pdf | cut -d: -f1 | sort -u 

Nachdem Sie den obigen Befehl ausgeführt und sichergestellt haben, dass er die erwartete Ausgabe generiert, können Sie ihn mit dem Bash- Befehl substituation ( $()) und history extension ( !!) schnell erneut ausführen und die Dateien wie folgt verschieben:

$ mv $(!!) ./destination 

Natürlich können Sie stattdessen den gesamten Befehl erneut eingeben, wenn Sie möchten:

$ mv -i $(pdfgrep -i "Fatima Alves" *.pdf | cut -d: -f1 | sort -u) ./destination 

Beachten Sie, dass dies unter zwei Umständen fehlschlagen wird:

  1. Der pathologische Fall, in dem keine Dateien mit dem Muster übereinstimmen, führt zu einem etwas kryptischen Fehler, der Folgendes sagt: mv: missing destination file operand after './destination'
  2. Dateien mit Leerzeichen im Namen verursachen Probleme.

Ich persönlich habe mir nicht die Mühe gemacht, eine Problemumgehung für diese beiden Fehlermodi zu finden, da ich solche 'match + action'-Befehle immer in zwei Schritten ablaufe (daher weiß ich immer, ob es null Übereinstimmungen gab und die Aktion daher übersprungen werden kann) und Ich vermeide gewissenhaft Dateinamen mit Leerzeichen. Bei Bedarf können Sie jedoch | sed 's/ /\\ /gam Ende der Befehlsersetzungspipeline etwas hinzufügen, um die Leerzeichen zu umgehen.