problema ao citar a saída ls

problema ao citar a saída ls

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 desejo, portanto quero passar sua saída para conversão.

eu tentei

convert `ls -v *png` out.pdf

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

Dizendo lspara definir os nomes dos arquivos entre aspas duplas via

convert `ls -vQ *png` out.pdf

também não funciona, pois as aspas parecem ser removidas na substituição.

O que posso fazer?

Responder1

Se você tiver um sistema recente baseado em GNU (que sortfornece uma classificação de versão natural semelhante -V), poderá classificar usando-o e ler o resultado em uma matriz:

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

Então você poderá expandir o array dentro do seu convertcomando:

convert "${files[@]}" out.pdf

Responder2

Se os nomes dos seus arquivos não tiverem novas linhas, você poderá fazer isso apenas dizendo ao shell para dividir a saída lsapenas em novas linhas, e não em qualquer espaço em branco como padrão. Odivisãoé controlado pela IFSvariável, quaisquer caracteres contidos em IFSsã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 lsos confundirem para exibição. Ao imprimir em um terminal, lsgeralmente 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 -1tivesse sido fornecida.


Para trabalhar com a ideia com a qual você começou, vocêpoderiausar eval.

eval: eval [arg ...]
Combine ARGs em uma única string, use o resultado como entrada para o shell e execute os comandos resultantes.

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

Além disso, se você seguir esse caminho, convém usar --quoting-style=shellem vez de, -Qpois pode corresponder mais ao processamento dos caracteres especiais do shell. (Ambos podem ser específicos do GNU ls, mas acho que -vtambém são.)

Responder3

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

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

Em um sistema GNU, com bash, zsh, yashou mksh:ksh93

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

Responder4

Usando GNU Parallel fica assim:

ls -vd ./*png | parallel -Xj1 convert {} out.pdf

informação relacionada