Я пытаюсь написать сценарий bash, который будет читать несколько имен файлов и целевой каталог, что не является обязательным.
./myfile -t /home/users/ file1 file2
Я пробовал следующий код, но я не могу обрабатывать различные сценарии, упомянутые ниже:
while getopts "t:" opt; do
case $opt in
t)
echo "-t was triggered, Parameter: $OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG"
exit 1
;;
:)
echo "Option -$OPTARG requires an argument."
exit 1
;;
esac
done
Но код должен обрабатывать разные сценарии, например:
./myfile file1 file2 -t /home/users/
,
./myfile file1 -t /home/users/ file2 file3
,
./myfile file1 file2 file3 file4
и должен иметь возможность читать файлы.
В этом случае использование цикла while
для read
и shift
аргументов может быть проще.
В приведенном ниже примере аргументы перебираются в цикле для поиска строки -t
, и в этом случае массив аргументов сдвигается на один шаг, а теперь предполагается, что индекс nr 1 является необязательным домашним каталогом. Во всех остальных случаях элемент перемещается в другой массив с именем files
.
#! /bin/bash
files=()
homedir=
while (( $# > 0 )); do
case "$1" in
-t )
shift
homedir = "$1"
;;
* )
files+=("$1")
;;
esac
shift
done
echo "${files[@]}"
echo "$homedir"
После цикла while
вам нужно shift
удалить все параметры и их аргументы. Это работает, даже если нет аргументов flags/flag.
shift $(($OPTIND - 1))
Тогда остальные аргументы доступны в "$@"
и могут быть обработаны любым из обычных способов. Например:
for arg in "$@"
do
something_with "$arg"
done
Для получения дополнительной информации см. мой ответ здесь.
«Традиционный» синтаксис команды unix требует, чтобы параметры стояли перед позиционными параметрами, и это то, что поддерживает
getopts
. Если вы хотите разрешить параметры позже в последовательности, вам нужно выполнить синтаксический анализ самостоятельно.