problema al citar la salida de ls

problema al citar la salida de ls

Quiero unir algunos archivos png en un pdf. El comando

convert *png out.pdf

Funciona, pero hace el pedido mal. Resulta que

ls -v *png

da el orden que quiero, por lo tanto quiero pasar su resultado para convertirlo.

Yo he tratado

convert `ls -v *png` out.pdf

pero esto no funciona ya que los nombres de los archivos contienen espacios y paréntesis.

Indicar lsque se establezcan los nombres de archivos entre comillas dobles mediante

convert `ls -vQ *png` out.pdf

tampoco funciona ya que las comillas parecen eliminarse en la sustitución.

¿Qué puedo hacer?

Respuesta1

Si tiene un sistema reciente basado en GNU (que sortproporciona una -Vclasificación de versión natural similar), puede ordenar usando eso y leer el resultado en una matriz:

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

Entonces deberías poder expandir la matriz dentro de tu convertcomando:

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

Respuesta2

Si los nombres de sus archivos no tienen líneas nuevas, es posible que pueda hacerlo simplemente diciéndole al shell que divida la salida lssolo en líneas nuevas, no en espacios en blanco como valor predeterminado. Elterribleestá controlado por la IFSvariable, todos los caracteres contenidos en IFSse utilizan como delimitadores.

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

Esto aún puede tener problemas si los nombres de los archivos son lo suficientemente divertidos o si lslos modifica para mostrarlos. Al imprimir en una terminal, lsnormalmente se enumeran los archivos en varias columnas. Pero cuando la salida no va a una terminal (el shell lo lee aquí), actúa como si -1estuviera dada.


Para trabajar con la idea con la que empezaste, debespodríausar eval.

eval: eval [arg...]
Combine ARG en una sola cadena, use el resultado como entrada al shell y ejecute los comandos resultantes.

Pero el problema evales que todo lo que está en la línea de comando se analiza nuevamente, e incluso las cosas que normalmente son seguras, no lo son. Piense en un archivo llamado $(touch HELLO)y qué sucede si un nombre como ese se coloca en la línea de comando.

Además, si sigue este camino, es posible que desee utilizar --quoting-style=shellen lugar de, -Qya que puede coincidir más estrechamente con el procesamiento de los caracteres especiales por parte del shell. (Ambos pueden ser específicos de GNU ls, pero creo que -vtambién lo son).

Respuesta3

Con zsh, el (n)calificador global le proporciona un orden de clasificación similar al de GNU ls -v:

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

En un sistema GNU, con bash, zsh, yash, mksho ksh93:

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

Respuesta4

Usando GNU Parallel se ve así:

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

información relacionada