Как определить оболочку script с переменным числом аргументов?
Я хотел бы определить простую аббревиатуру вызова gs
(ghostscript) через оболочку script. Первый аргумент дает все файлы, которые должны быть объединены, а последний - имя выходного файла. Очевидно, что следующее не работает (это просто для показа цели):
#!/bin/sh
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=$last $1 $2 ...
Как это можно сделать?
Обычно можно назвать этот script через myscript infile1.pdf infile2.pdf ... outfile.pdf
или myscript *.pdf outfile.pdf
.
Ответы
Ответ 1
Переменные bash [email protected]
и $*
расширяются в список аргументов командной строки. Как правило, вы захотите использовать "[email protected]"
(то есть [email protected]
, окруженный двойными кавычками). Это будет сделано правильно, если кто-то передаст ваш script аргумент, содержащий пробелы.
Итак, если у вас есть это в script:
outputfile=$1
shift
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=$outputfile "[email protected]"
И вы вызвали свой script следующим образом:
myscript out.pdf foo.ps bar.ps "another file.ps"
Это будет расширяться до:
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=out.pdf foo.ps bar.ps "another file.ps"
Подробнее читайте раздел "Специальные параметры" справочной страницы bash
.
Ответ 2
Чтобы передать выходной файл в качестве последнего аргумента, используйте массив:
ARGS=("[email protected]")
# Get the last argument
outputfile=${ARGS[-1]}
# Drop it from the array
unset ARGS[${#ARGS[@]}-1]
exec gs ... -sOUTPUTFILE=$outputfile "${ARGS[@]}"
До версии 4 bash
не разрешали отрицательные индексы в массивах (и приводили ошибку, о которой сообщал Marius в комментариях), поэтому, если вы используете 3.x, вам нужно использовать гораздо более уродливые
outputfile=${ARGS[${#ARGS[@]}-1]}
Это работает и для bash 4.x.
Ответ 3
Чтобы получить доступ к последнему аргументу, в дополнение к ответу, указанному выше, вы также можете сделать:
echo "${@: $#}"
Это считывает все аргументы и печатает их, начиная с последнего. Таким образом, вы также можете получить доступ к последним аргументам N, например, для трех последних аргументов:
echo "${@: $#-2}"
$ ./script "what does" "this script" "do" "?"
this script do ?