No se puede hacer que la construcción xargs funcione

No se puede hacer que la construcción xargs funcione

tengo un problema extraño conxargos.
Yo tengo unxargosconstrucción que no funciona, aunque cuando repito el comando, funciona perfectamente. Mi única línea es la siguiente:

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

y la salida

Error: No se puede encontrar el archivo. Error: No se pudo abrir el archivo PDF: 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf

  • Selecciona exiftooltodos los pdf que contienen la palabra DATOS en la etiqueta de asunto,
  • Las -p exifprintformatinstrucciones exiftoolpara imprimir solo el nombre del archivo,
  • Selecciona grepsolo las líneas con pdf,
  • El sedelimina espacios en blanco,
  • El primero xargconvierte todas las líneas en una sola cadena y el segundo construye el comando de vinculación) cuando ejecuto

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

yo obtengo

pdftk 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf carpeta de salida cat1.pdf

que funciona perfectamente.

Evidentemente estoy haciendo algo mal... ¿Pero qué?

Respuesta1

Hay varias cosas mal y complejidad innecesaria: -

  1. La llamada doble xargssignifica que la segunda ve una sola línea de entrada, por lo que {}se sustituye solo una vez con una sola cadena que comprende todos los nombres de archivos coincidentes, pero echono muestra esta diferencia en la salida (compárese echo a bcon echo "a b").
  2. El -0argumento significa que xargsse necesita un '\0'carácter nulo ( ) entre los argumentos de entrada, y no hay ninguno; esto también obliga a que la entrada se trate como un único parámetro.
  3. Al generar solo el nombre del archivo cuando la condición coincide, obtiene un nombre de archivo por línea, al que se puede canalizar directamente xargssin la necesidad de grepo sed.
  4. Desafortunadamente, xargs -Ifuerza un comando por línea de entrada y no hay opción para agregar parámetros finales, pero hay una solución simple: agregar los parámetros finales al flujo de entrada.

Este es un comando simplificado con los parámetros finales agregados (lo probé con una -ifcondición diferente y no tenía ningún archivo PDF que coincidiera): -

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

La xargs -d'\n'opción hace que el comando funcione cuando los nombres de los archivos tienen espacios en blanco incrustados.

Respuesta2

La página de manual de xargs dice:

-reemplazo-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.

En otras palabras, terminarás con un único argumento llamado " 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf"

Sugiero deshacerse de xargs por completo y reordenar su comando de esta manera:

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

Todo esto supone que no tienes espacios en tus nombres de archivos (suposición segura ya que de todos modos estabas eliminando todos los espacios con sed).

información relacionada