проблема с цитированием вывода ls

проблема с цитированием вывода ls

Я хочу объединить несколько 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

Связанный контент