problema com a citação da saída ls

2

Eu quero juntar alguns arquivos png em um pdf. O comando

convert *png out.pdf

funciona, mas erra a ordem. Acontece que

ls -v *png

dá a ordem que eu quero, portanto, quero passar sua saída para converter.

Eu tentei

convert 'ls -v *png' out.pdf

mas isso não funciona, pois os nomes dos arquivos contêm espaços e parênteses.

Dizendo ls para definir os nomes dos arquivos entre aspas duplas via

convert 'ls -vQ *png' out.pdf

não funciona porque as cotações parecem ser removidas na substituição.

O que posso fazer?

    
por user313032 23.09.2016 / 00:13

4 respostas

1

Se os nomes dos seus arquivos não tiverem nenhuma nova linha, você poderá fazê-lo apenas informando ao shell para dividir a saída de ls apenas em novas linhas, e não em nenhum espaço em branco como padrão. A divisão é controlada pela variável IFS , todos os caracteres contidos em IFS são usados como delimitadores.

IFS=$'\n'      # set it to just a newline
convert $(ls -vd ./*.png) output.pdf 

Isso ainda pode ter problemas se os nomes dos arquivos forem engraçados o suficiente ou se ls os manuseia para exibição. Ao imprimir em um terminal, ls geralmente lista os arquivos em várias colunas. Mas quando a saída não vai para um terminal (o shell lê, aqui), ela age como se -1 fosse dado.

Para trabalhar com a ideia que você começou, você poderia usar eval .

eval: eval [arg ...]
Combine ARGs into a single string, use the result as input to the shell, and execute the resulting commands.

Mas o problema com eval é que qualquer coisa e tudo na linha de comando é analisado novamente, e até mesmo coisas que normalmente são seguras, não são. Pense em um arquivo chamado $(touch HELLO) e o que acontece se um nome como esse for solto na linha de comando.

Além disso, se você seguir esse caminho, talvez queira usar --quoting-style=shell em vez de -Q , pois ele pode corresponder mais de perto ao processamento do shell dos caracteres especiais. (Ambos podem ser específicos do GNU ls, mas acho que -v também é.)

    
por 23.09.2016 / 00:56
2

Se você tem um sistema baseado em GNU recente (cujo sort fornece uma classificação -V natural-version similar) você pode classificar usando isso e ler o resultado em uma matriz:

while read -rd '' f; do 
  files+=("$f")
done < <(find . -maxdepth 1 -name '*png' -print0 | sort -zV)

Em seguida, você poderá expandir o array no comando convert :

convert "${files[@]}" out.pdf
    
por 23.09.2016 / 02:08
1

Com zsh , o qualificador (n) glob fornece uma ordem de classificação semelhante à do GNU ls -v :

convert ./*.png(n) out.pdf

Em um sistema GNU, com bash , zsh , yash , mksh ou ksh93 :

eval "files=($(ls --quoting-style=shell-always -vd ./*.png))"
convert "${files[@]}" out.pdf
    
por 23.09.2016 / 17:42
0

Usando o GNU Parallel, é assim:

ls -vd ./*png | parallel -Xj1 convert {} out.pdf
    
por 23.09.2016 / 17:36

Tags