Xargs-Konstrukt funktioniert nicht

Xargs-Konstrukt funktioniert nicht

Ich habe ein seltsames Problem mitxargs.
Ich habe einxargsKonstrukt, das nicht funktioniert, obwohl es perfekt funktioniert, wenn ich den Befehl wiedergebe. Mein Einzeiler ist der folgende:

 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 konnte nicht gefunden werden. Fehler: PDF-Datei konnte nicht geöffnet werden: 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf

  • Das exiftoolwählt alle PDFs aus, die das Wort DATA im Betreff-Tag enthalten.
  • Die -p exifprintformatAnweisung, exiftoolnur den Dateinamen auszudrucken,
  • Das grepwählt nur die Zeilen mit pdf aus,
  • Das sedentfernt Leerzeichen,
  • Die erste xargmacht alle Zeilen zu einem String und die zweite erstellt den Bind-Befehl), wenn ich

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

Ich bekomme

pdftk 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf cat-Ausgabe binder1.pdf

was perfekt funktioniert.

Offensichtlich mache ich etwas falsch ... Aber was?

Antwort1

Mehrere Dinge sind falsch und es besteht eine unnötige Komplexität: -

  1. Der doppelte xargsAufruf bedeutet, dass der zweite Aufruf eine einzelne Eingabezeile sieht und diese daher {}nur einmal durch eine einzelne Zeichenfolge ersetzt wird, die alle übereinstimmenden Dateinamen enthält. echoIn der Ausgabe zeigt sich dieser Unterschied jedoch nicht (vergleichen Sie echo a bmit echo "a b").
  2. Das -0Argument bedeutet, dass zwischen den Eingabeargumenten xargsein Nullzeichen () erforderlich ist , es jedoch keines gibt. Dadurch wird auch erzwungen, dass die Eingabe als einzelner Parameter behandelt wird.'\0'
  3. Indem nur der Dateiname ausgegeben wird, wenn die Bedingung erfüllt ist, erhalten Sie einen Dateinamen pro Zeile, an den direkt weitergeleitet werden kann, ohne dass oder xargserforderlich ist .grepsed
  4. Leider xargs -Iwird ein Befehl pro Eingabezeile erzwungen und es besteht keine Möglichkeit, nachfolgende Parameter hinzuzufügen. Es gibt jedoch eine einfache Problemumgehung: Fügen Sie die nachfolgenden Parameter zum Eingabestrom hinzu.

Dies ist ein vereinfachter Befehl mit hinzugefügten nachfolgenden Parametern (ich habe ihn unter einer anderen -ifBedingung getestet, da ich keine übereinstimmenden PDFs hatte): -

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

Die xargs -d'\n'Option bewirkt, dass der Befehl funktioniert, wenn die Dateinamen eingebettete Leerzeichen enthalten.

Antwort2

Auf der Manpage für xargs heißt es:

-I ersetze-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.

Mit anderen Worten, Sie erhalten am Ende ein einzelnes Argument namens " 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf"

Ich schlage vor, xargs ganz wegzulassen und Ihren Befehl etwa so neu anzuordnen:

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

Dies alles setzt voraus, dass Ihre Dateinamen keine Leerzeichen enthalten (sichere Annahme, da Sie ohnehin alle Leerzeichen mit sed entfernt haben).

verwandte Informationen