Xargs-Konstrukt kann nicht funktionieren

441
Grigoris L.

Ich habe ein seltsames Problem mit Xargs .
Ich habe ein Xargs- Konstrukt, das nicht funktioniert, auch wenn ich den Befehl wiederholt, funktioniert es perfekt. Mein einziger Liner ist folgender:

 exiftool -p exifprintformat -if '$Subject =~/DATA/i' -q *.pdf |grep pdf |sed 's/ //g'|xargs|xargs -0 -I % pdftk % cat output binder1.pdf 

und die Ausgabe

Fehler: Datei kann nicht gefunden werden. Fehler: PDF-Datei konnte nicht geöffnet werden: 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf

  • Das exiftoolwählt alle PDF-Dateien aus, die das Wort DATA im Betreff-Tag enthalten.
  • Der -p exifprintformatBefehl exiftool, nur den Dateinamen zu drucken,
  • Das grepwählt nur die Zeilen mit pdf aus,
  • Das sedentfernt Leerzeichen,
  • Bei der ersten werden xargalle Zeilen zu einer Zeichenfolge, und bei der zweiten wird der Befehl zum Binden erstellt, wenn ich den Befehl ausführe

exiftool -p exifprintformat -if '$ Betreff = ~ / DATA / i' -q * .pdf | grep pdf | sed's / // g '| xargs | xargs -I {} echo pdftk {} cat-Ausgabemappe1.pdf

Ich bekomme

pdftk 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf Ausgangsbuch für die Katze1.pdf

das funktioniert perfekt.

Offensichtlich mache ich etwas falsch ... Aber was?

0
"grep" erwartet Zeilenende (wahrscheinlich vorhanden) und "darfst -0" erwartet NUL-Bytes (wahrscheinlich fehlt). eckes vor 6 Jahren 0

2 Antworten auf die Frage

0
woolfie

The man page for xargs says:

-I replace-str

 Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not terminate input items; instead the separator is the newline character. Implies -x and -L 1. 

In other words, you're ending up with a single argument called "20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf"

I suggest ditching xargs altogether and re-ordering your command something like this:

pdftk $(exiftool -p exifprintformat -if '$Subject =~/DATA/i' -q *.pdf |grep pdf |sed 's/ //g'| tr '\n' ' ') cat output binder1.pdf 

This all assumes you don't have spaces in your filenames (safe assumption since you were removing all spaces with sed anyway).

Thnx! Als Neuling musste dieser subtile Unterschied (Argument vs. Argumente) für mich festgelegt werden ... Newbie aha moment .. Mein früheres Verständnis war, dass xargs den Befehl shell oder etwas ausführte, um den Befehl auszuführen ... Offensichtlich nicht so .. . Grigoris L. vor 6 Jahren 0
0
AFH

There are several things wrong, and unnecessary complexity:-

  1. The double xargs call means that the second sees a single line of input, so {} is substituted just once with a single string comprising all the matching file names, but echo does not show this difference in the output (compare echo a b with echo "a b").
  2. The -0 argument means that xargs needs a null ('\0') character between input arguments, and there are none; this also forces the input to be treated as a single parameter.
  3. By outputting only the file name when the condition matches, you get one file name per line, which can be piped directly to xargs without the need for grep or sed.
  4. Unfortunately, xargs -I forces one command per line of input, and there is no option to add trailing parameters, but there is a simple work-round: add the trailing parameters to the input stream.

This is a simplified command with the trailing parameters added (I tested with a different -if condition, not having any PDFs which match):-

{ exiftool -p '$' -if '$Subject =~/DATA/i' -q *.pdf; \ echo -e "cat\noutput\nbinder1.pdf"; } | xargs -d'\n' pdftk 

The xargs -d'\n' option makes the command work when the file names have embedded blanks.

thnx für die ausführliche Antwort, und um alle Fehler zu lokalisieren .. Habe für die Bemerkung 3 einige Zweifel, da exiftool außer den Dateinamen auch zwei Zeilen ausgibt, die herausgeworfen werden müssen .. Grigoris L. vor 6 Jahren 0
@GrigorisL. - Alles, was ich sagen kann, ist, dass der Befehl für mich gut funktioniert, und der Befehl 'exiftool', den ich zitiert habe, erzeugt nur eine einzige Zeile mit dem Dateinamen. Für das Protokoll ist meine "exiftool" -Version 10.10 und ich verwende Ubuntu 16.04. AFH vor 6 Jahren 0
@ AFF Du hast doch recht. Wenn der -p $ -Dateiname von der Bash aufgerufen wird, werden nur Dateinamen ausgegeben. Wenn sie aus einer Parameterdatei aufgerufen wird, wie ich sie ursprünglich gemacht habe, ist die Ausgabe verblüfft. Grigoris L. vor 6 Jahren 0
OK, aber ich habe $ als einzige Zeile in einer Datei (keine Kommentare, Kopfzeilen usw.) angegeben, und das hat genauso gut funktioniert. Ich habe die Inline-Zeichenfolge zum Testen verwendet und da mein endgültiges Format so einfach war, schien es sinnlos, es in einer separaten Datei zu speichern. Übrigens sind `{}` in diesem Fall optional: Das einfachere `$ FileName` ist gleichwertig. AFH vor 6 Jahren 0