
Я хочу объединить несколько png-файлов в pdf. Команда
convert *png out.pdf
работает, но делает неправильный порядок. Оказывается, что
ls -v *png
дает нужный мне порядок, поэтому я хочу передать его вывод в convert.
я пытался
convert `ls -v *png` out.pdf
но это не работает, так как имена файлов содержат пробелы и скобки.
Указание ls
установить имена файлов в двойных кавычках через
convert `ls -vQ *png` out.pdf
тоже не работает, так как кавычки, похоже, удаляются при замене.
Что я могу сделать?
решение1
Если у вас есть последняя система на базе GNU (которая sort
предоставляет похожую -V
естественную версию сортировки), вы можете выполнить сортировку с ее помощью и прочитать результат в массив:
while read -rd '' f; do
files+=("$f")
done < <(find . -maxdepth 1 -name '*png' -print0 | sort -zV)
Затем вы сможете расширить массив в своей convert
команде:
convert "${files[@]}" out.pdf
решение2
Если в именах ваших файлов нет символов новой строки, вы можете сделать это, просто указав оболочке разбить вывод ls
только по символам новой строки, а не по пробелам, как это делается по умолчанию.расщеплениеуправляется переменной IFS
, любые символы, содержащиеся в ней, IFS
используются в качестве разделителей.
IFS=$'\n' # set it to just a newline
convert $(ls -vd ./*.png) output.pdf
Это все еще может иметь проблемы, если имена файлов достаточно забавны или если ls
они искажаются для отображения. При печати на терминале ls
обычно перечисляет файлы в нескольких столбцах. Но когда вывод не идет на терминал (оболочка читает его здесь), он действует так, как будто -1
был дан.
Чтобы работать с идеей, с которой вы начали, ваммогиспользовать eval
.
eval: eval [arg ...]
Объединяет ARG в одну строку, использует результат в качестве входных данных для оболочки и выполняет полученные команды.
Но проблема в eval
том, что все и вся в командной строке анализируется снова, и даже то, что обычно безопасно, не анализируется. Подумайте о файле с именем $(touch HELLO)
и что произойдет, если такое имя будет добавлено в командную строку.
Кроме того, если вы пойдете этим путем, вы можете использовать --quoting-style=shell
вместо , -Q
так как это может более точно соответствовать обработке оболочкой специальных символов. (Оба могут быть специфичны для GNU ls, но я думаю -v
, что это тоже так.)
решение3
С помощью zsh
квалификатора (n)
glob вы получите порядок сортировки, аналогичный GNU ls -v
:
convert ./*.png(n) out.pdf
В системе GNU с bash
, zsh
, yash
, mksh
или ksh93
:
eval "files=($(ls --quoting-style=shell-always -vd ./*.png))"
convert "${files[@]}" out.pdf
решение4
С использованием GNU Parallel это выглядит так:
ls -vd ./*png | parallel -Xj1 convert {} out.pdf