Não é possível fazer construções de xargs para funcionar

0

Eu tenho um problema estranho com xargs .
Eu tenho uma construção xargs que não funciona, embora quando eu ecoo o comando, funciona perfeitamente. Meu um forro é o seguinte:

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

e a saída

Error: Unable to find file. Error: Failed to open PDF file: 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf

  • O exiftool seleciona todo o pdf que contém a palavra DATA na tag de assunto,
  • O -p exifprintformat instrui exiftool a imprimir apenas o nome do arquivo,
  • O grep seleciona apenas as linhas com pdf,
  • O sed remove os espaços em branco,
  • O primeiro xarg faz todas as linhas em uma string e a segunda constrói o comando bind quando eu corro

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

Eu obtenho

pdftk 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf cat output binder1.pdf

que funciona perfeitamente.

Obviamente, estou fazendo algo errado ... Mas o que?

    
por Grigoris L. 21.06.2017 / 18:39

2 respostas

0

Existem várias coisas erradas e complexidade desnecessária: -

  1. A chamada xargs dupla significa que a segunda vê uma única linha de entrada, então {} é substituído apenas uma vez por uma única string contendo todos os nomes de arquivos correspondentes, mas echo não mostra essa diferença na saída (compare echo a b com echo "a b" ).
  2. O argumento -0 significa que xargs precisa de um caractere nulo ( 'xargs' ) entre os argumentos de entrada e não há nenhum; isso também força a entrada a ser tratada como um único parâmetro.
  3. Ao exibir apenas o nome do arquivo quando a condição corresponde, você obtém um nome de arquivo por linha, que pode ser canalizado diretamente para grep sem a necessidade de sed ou xargs -I .
  4. Infelizmente, -if força um comando por linha de entrada e não há opção para adicionar parâmetros à direita, mas há uma rodada de trabalho simples: adicione os parâmetros à direita do fluxo de entrada.

Este é um comando simplificado com os parâmetros finais adicionados (testei com uma condição xargs -d'\n' diferente, não tendo nenhum PDF correspondente): -

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

A opção %code% faz o comando funcionar quando os nomes dos arquivos possuem espaços em branco incorporados.

    
por 21.06.2017 / 22:05
0

A página man do xargs diz:

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

Em outras palavras, você está terminando com um único argumento chamado " 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf "

Sugiro trocar os xargs por completo e reordenar o seu comando assim:

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

Isto tudo assume que você não tem espaços em seus nomes de arquivos (suposição segura desde que você estava removendo todos os espaços com sed mesmo assim).

    
por 21.06.2017 / 19:28

Tags