bash: Passando vários espaços contendo nomes de arquivos

1

Em um script bash estou rasterizando uma página PDF por página em arquivos únicos, no final, os únicos PNGs resultantes são mesclados novamente em um PDF como este:

convert -monitor /path/to/1.png /path/to/2.png /path/to/3.png ... output.pdf

O único problema que o script ainda possui é a incapacidade de manipular corretamente os arquivos com espaços. Aqui estão algumas das coisas que eu tentei:

newfile=$(sed -r -e 's| |\ |g' <<< "$tmppath$curr.png")
echo "DEBUG: newfiles : $newfiles"
filearray[$curr-1]="$newfiles"
echo "DEBUG: filearray: ${filearray[*]}"

Isso produz (por página / arquivo):

DEBUG: newfiles : /tmp/pngpdf/file\ with\ spaces/1.png
DEBUG: filearray: /tmp/pngpdf/file\ with\ spaces/1.png

Mais tarde, tenho duas mensagens de depuração

echo "DEBUG: filearray: ${filearray[*]}"
echo "DEBUG:            ${filearray[0]}, ${filearray[1]}, ${filearray[2]}, ..."

para ver como o filearray se parece com vários arquivos / páginas:

DEBUG: filearray: /tmp/pngpdf/file\ with\ spaces/1.png /tmp/pngpdf/file\ with\ spaces/2.png /tmp/pngpdf/file\ with\ spaces/3.png /tmp/pngpdf/file\ with\ spaces/4.png /tmp/pngpdf/file\ with\ spaces/5.png
DEBUG:            /tmp/pngpdf/file\ with\ spaces/1.png, /tmp/pngpdf/file\ with\ spaces/2.png, /tmp/pngpdf/file\ with\ spaces/3.png, ...

E posso ver claramente o seguinte:

  1. Para cada arquivo, há exatamente um elemento de matriz.
  2. Todo espaço é precedido por \ .

Estou colocando o comando inteiro em uma variável primeiro para ver o que seria executado:

execcmd="convert -monitor ${filearray[@]} output.pdf"

Um exemplo pode parecer assim:

convert -monitor /tmp/pngpdf/file\ with\ spaces/1.png /tmp/pngpdf/file\ with\ spaces/2.png /tmp/pngpdf/file\ with\ spaces/3.png /tmp/pngpdf/file\ with\ spaces/4.png /tmp/pngpdf/file\ with\ spaces/5.png output.pdf

Mas executar isso com $execcmd convert está causando inúmeros erros em mim:

convert.im6: unable to open image '/tmp/pngpdf/file\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format '/tmp/pngpdf/file\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'with\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format 'with\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'spaces/1.png': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: unable to open file 'spaces/1.png' @ error/png.c/ReadPNGImage/3667.
convert.im6: unable to open image '/tmp/pngpdf/file\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format '/tmp/pngpdf/file\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'with\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format 'with\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'spaces/2.png': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: unable to open file 'spaces/2.png' @ error/png.c/ReadPNGImage/3667.
convert.im6: unable to open image '/tmp/pngpdf/file\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format '/tmp/pngpdf/file\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'with\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format 'with\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'spaces/3.png': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: unable to open file 'spaces/3.png' @ error/png.c/ReadPNGImage/3667.
convert.im6: unable to open image '/tmp/pngpdf/file\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format '/tmp/pngpdf/file\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'with\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format 'with\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'spaces/4.png': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: unable to open file 'spaces/4.png' @ error/png.c/ReadPNGImage/3667.
convert.im6: unable to open image '/tmp/pngpdf/file\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format '/tmp/pngpdf/file\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'with\': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no decode delegate for this image format 'with\' @ error/constitute.c/ReadImage/544.
convert.im6: unable to open image 'spaces/5.png': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: unable to open file 'spaces/5.png' @ error/png.c/ReadPNGImage/3667.
convert.im6: no images defined 'output.pdf' @ error/convert.c/ConvertImageCommand/3044.

Obviamente, não reconhece o que quero fazer corretamente. As barras invertidas escapam e, assim, os espaços recuperam seus poderes de delimitação de argumentos. Ao colocar esse comando no bash diretamente, ele corre suavemente (como esperado):

$ convert -monitor /tmp/pngpdf/file\ with\ spaces/1.png /tmp/pngpdf/file\ with\ spaces/2.png /tmp/pngpdf/file\ with\ spaces/3.png /tmp/pngpdf/file\ with\ spaces/4.png /tmp/pngpdf/file\ with\ spaces/5.png output.pdf
Load/Image//tmp/pngpdf/file with spaces[1.png]: 584 of 585, 100% complete
Load/Image//tmp/pngpdf/file with spaces[2.png]: 584 of 585, 100% complete
Load/Image//tmp/pngpdf/file with spaces[3.png]: 584 of 585, 100% complete
Load/Image//tmp/pngpdf/file with spaces[4.png]: 584 of 585, 100% complete
Load/Image//tmp/pngpdf/file with spaces[5.png]: 584 of 585, 100% complete
Mogrify/Image//tmp/pngpdf/file with spaces[5.png]: 4 of 5, 100% complete
resize image[output.pdf]: 180 of 181, 100% complete
resize image[output.pdf]: 180 of 181, 100% complete
resize image[output.pdf]: 180 of 181, 100% complete
resize image[output.pdf]: 180 of 181, 100% complete

Isso me deixa muito perplexo e não tenho ideia de como consertar isso. Eu tentei salvar os nomes de arquivo único citados em filearray, assim que eu iria receber DEBUG: filearray: "/tmp/pngpdf/file with spaces/1.png" "/tmp/pngpdf/file with spaces/2.png" "/tmp/pngpdf/file with spaces/3.png" "/tmp/pngpdf/file with spaces/4.png" "/tmp/pngpdf/file with spaces/5.png" sem sucesso. Provavelmente bash escapa desses caracteres especiais também. Tenho certeza de que deve ter a ver com a forma como o bash funciona, mas parece que meu entendimento ainda não é bom o suficiente para consertar isso sozinho. Então, eu ficaria muito feliz se alguém pudesse me esclarecer. :)

PS: Estou procurando uma resposta para minha pergunta em vários lugares ( Problema de script de shell com nomes de arquivos contendo espaços , Usando uma lista gerada de nomes de arquivos como lista de argumentos - com espaços , Looping através de arquivos com espaços nos nomes? , Bash scripting e arquivos com espaços neles , Por que meu script de shell sufoca em espaços em branco ou outros caracteres especiais? , Problema no script com espaços no nome do arquivo ). Infelizmente, não consegui localizar uma resposta para a minha pergunta. Talvez seja tarde demais;)

    
por Kreuvf 27.06.2015 / 00:48

1 resposta

3

execcmd="convert -monitor ${filearray[@]} output.pdf"

But executing that with $execcmd convert is throwing numerous errors at me

Não chame $execcmd , pois ele já perdeu a diferenciação entre nomes de arquivos e partes separadas por espaços de nomes de arquivos. Em vez disso, execute o próprio comando com argumentos citados:

    convert -monitor "${filearray[@]}" output.pdf
    
por 27.06.2015 / 01:08