У меня есть этот список файлов PDF в каталоге:
c0.pdf c12.pdf c15.pdf c18.pdf c20.pdf c4.pdf c7.pdf
c10.pdf c13.pdf c16.pdf c19.pdf c2.pdf c5.pdf c8.pdf
c11.pdf c14.pdf c17.pdf c1.pdf c3.pdf c6.pdf c9.pdf
Я хочу объединить их, используя ghostscript в числовом порядке (похоже на это):
gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf *.pdf
Но порядок расширения оболочки воспроизводит не естественный порядок чисел, а алфавитный порядок:
$ for f in *.pdf; do echo $f; done
c0.pdf
c10.pdf
c11.pdf
c12.pdf
c13.pdf
c14.pdf
c15.pdf
c16.pdf
c17.pdf
c18.pdf
c19.pdf
c1.pdf
c20.pdf
c2.pdf
c3.pdf
c4.pdf
c5.pdf
c6.pdf
c7.pdf
c8.pdf
c9.pdf
Как можно добиться желаемого порядка в расширении (если это возможно, без добавления вручную 0
-padding к числам в именах файлов)?
Я нашел предложения для использования ls | sort -V
, но я не мог заставить его работать для моего конкретного случая использования.
Ответы:
В зависимости от вашей среды вы можете использовать
ls -v
с GNU coreutils, например:Или, если вы используете последние версии FreeBSD или OpenBSD:
источник
ls -v
будетnatural sort of (version) numbers within text
так, что может быть использовано также ...-V
особенностьsort
не определен POSIX либо. Однако, похоже, что он распространился дальше, например, как FreeBSD, так и OpenBSDsort
его поддерживают.ls
использованный, я проверил, есть ли у него опция вместо сортировки поЕще раз, глобальные классификаторы Zsh приходят на помощь.
источник
Если все рассматриваемые файлы имеют одинаковый префикс (т. Е. Текст перед номером;
c
в этом случае), вы можете использоватьc?.pdf
расширяется доc0.pdf
c1.pdf
...c9.pdf
.c??.pdf
расширяется доc10.pdf
c11.pdf
…c20.pdf
(и доc99.pdf
, если применимо). Хотя каждое слово командной строки, содержащее символы расширения пути, расширяется до списка имен файлов, отсортированных (сопоставленных) в соответствии сLC_COLLATE
переменной, списки, являющиеся результатом расширения смежных подстановочных знаков (глобусов), не объединяются; они просто соединены. (Кажется, я вспомнил, что на странице руководства по оболочке это прямо указывалось, но сейчас я не могу ее найти.)Конечно, если файлы могут идти до
c999.pdf
, вы должны использоватьc?.pdf c??.pdf c???.pdf
. Правда, это может быть утомительно, если у вас много цифр. Вы можете немного сократить его; например, для (до) пяти цифр вы можете использоватьc?{,?{,?{,?{,?}}}}.pdf
. Если ваш список имен файлов редкий (например, есть ac0.pdf
и ac12345.pdf
, но не обязательно каждое число между ними), вам, вероятно, следует установить этотnullglob
параметр. В противном случае, если (например) у вас нет файлов с двузначными числами, вы получите буквальныйc??.pdf
аргумент, переданный вашей программе.Если у вас есть несколько префиксов (например, , , и , с номерами одной или двух цифр), вы можете использовать очевидное, грубой силы подход:
a<number>.pdf
b<number>.pdf
c<number>.pdf
или свернуть
{a,b,c}?{,?}.pdf
.источник
ls
,stat
или что - нибудь еще; а также работает в bash по запросу.Если пробелов нет , следующее может оказаться полезным (хотя и отрывочным и не надежным в отношении краевых случаев и общности) - просто чтобы понять:
Если могут быть пробелы, некоторые
[ -f c${i}.pdf ]
проверки могут быть добавлены.Редактировать также посмотреть этот ответ , в соответствии с которым вы могли бы (используя Bash) использовать
источник
"$FILES"
и"$i"
), если у вас нет веских причин не делать этого, и вы уверены, что знаете, что делаете. (Напротив, хотя фигурные скобки могут быть важны, они не так важны, как кавычки, поэтому, например,"c$i.pdf"
достаточно хороши.) Такая команда, как , где содержится разделенный пробелами список файлов, может показаться хорошей причиной для используйте без кавычек (потому что не будет работать в этом контексте). … (Продолжение)gs [
…args…
] $FILES
$FILES
$FILES
"$FILES"
FILES=("c0.pdf")
иFILES+=("c$i.pdf")
); также этот ответ , который использует технику, которую я предлагаю.Просто цитирую и исправляю ответ Тора ... НИКОГДА не разбирайте!
Вы можете использовать
sort -V
(расширение не POSIX для сортировки):(для некоторых команд, очевидно, для gs такая команда, вам нужно "./ " вместо " " ... если одна не работает, попробуйте другую)
источник
stat
но с добавлением некоторых других проблем (например , проблемы с началом имен файлов с-
, проблема, если есть слишком много файлов,stat
будучи непереносимой командой). И поскольку вы использовали оператор split + glob без настройки IFS или отключения глобусов, у вас все равно будут проблемы с именами файлов с пробелом или символом табуляции или подстановочными символами.sort -V
надежно, вы должны были бы${(z)"$(printf '%s\0' * | sort -zV)"}
вzsh
(хотяzsh
есть(n)
для численного рода уже есть ) илиreadarray -td '' files < <(printf '%s\0' * | sort -zV)
вbash4.4+
.ls
одного (то есть без -l), каковы эти другие проблемы ? Обратите внимание, что--
это не поможет для файла с именем-
.touch \"test\"; ls -1
например, показы'"test"'
на моем ls. Он просто не предназначен для анализа ... это пользовательский интерфейс, а не команда сценариев.