Como evitar o escape duplo?

1

Estou tentando juntar várias imagens em um pdf. Eu corri gm convert *.jpg out.pdf e funcionou, mas as imagens não estavam na ordem correta.
Descobri que ls -v os ordena corretamente, então tentei gm convert 'ls -v *.jpg' out.pdf , mas isso falhou porque os arquivos têm espaços nos nomes.

Então eu verifiquei as opções ls e tentei gm convert 'ls -Qv *.jpg' out.pdf e gm convert 'ls -bv *.jpg' out.pdf , mas ambas falharam porque, até onde eu sei, os nomes dos arquivos escaparam duas vezes (usando \ "no primeiro caso e \\ antes do espaço no segundo caso).
Por que isso está acontecendo e como posso obter os nomes dos arquivos corretamente, ou seja, apenas uma vez? Estou usando o zsh se isso for relevante.

    
por aditsu 13.03.2013 / 07:12

1 resposta

3

Você não pode usar como escapar dessa maneira. Você pode usar aspas ou barras invertidas para algo que as entenda como a análise de shell.

Não há nada para escapar da divisão de palavras feita na expansão de variáveis ou na substituição de comandos (que é diferente da análise de shell (tokenising) de uma linha de comando).

O que você pode fazer é alterar o delimitador de campo interno $IFS para dividir apenas os caracteres de nova linha (mas observe que, exceto com zsh , também é necessário desativar a geração de nome de arquivo (embora não para a expansão de *.jpg obviamente) que é a outra coisa feita após a substituição de comando sem aspas, a menos que você possa garantir que nenhum nome de arquivo contenha caracteres globbing):

set -f # disable filename generation
IFS='
' # set IFS  to newline character
IFS=$'\n' # alternative for ksh/zsh/bash
gm convert $(set +f; ls -v ./*.jpg) out.pdf # you also need ./ in case file
                                            # names start with -

(que assume que nenhum dos nomes de arquivo contém caracteres de nova linha)

set -f in zsh (a menos que na emulação sh / ksh) desabilite a leitura de rc arquivos (pense em zsh -f , csh -f ), que não tem efeito uma vez que o shell já foi iniciado, portanto é inofensivo. / p>

Com zsh , você pode reduzir isso para:

gm convert ${(f)"$(ls -v ./*.jpg)"} out.pdf

(f) para (ps:\n:) é dividido em caracteres de nova linha.

Como alternativa, você pode usar o ls para criar uma linha de comando do shell (código do shell na sintaxe do shell, se desejar) para passar para eval , o que permitiria ao shell avaliá-lo e executá-lo:

Com ksh93 , zsh ou bash :

eval "images=($(ls --quoting-style=shell -v ./*.jpg))"
gm convert "${images[@]}" out.pdf

Mas com zsh , você poderia simplesmente fazer:

gm convert ./*.jpg(n) out.pdf

(n) é um qualificador globbing que diz ao shell para ordenar numericamente os nomes dos arquivos gerados.

    
por 13.03.2013 / 08:01