Это плохой код. getopt
практически непригоден¹. Вместо него используйте встроенную оболочку getopts
(у нее два преимущества: она может работать и доступна на всех POSIX платформах).
Что делает args=$(getopt optstring $*); set -- $args
:
getopt
. getopt
в переменной args
. Это строка, состоящая из аргументов командной строки, объединенных пробелами в качестве разделителя, и упорядоченная так, чтобы были опции и их аргументы, затем --
, затем операнды без опций. В оболочках типа Bourne/POSIX, $foo
- это оператор "split+glob". Чтобы получить значение переменной, нужны двойные кавычки: "$foo"
. Но в zsh $foo
работает по-другому: он расширяется до значения foo
, за исключением случаев, когда foo
пуст. Таким образом, в zsh вы получаете один позиционный параметр.
Первого использования оператора split+glob можно избежать, написав getopt optstring "$@"
: это передаст позиционные параметры точно в getopt
. Но при разборе вывода getopt
расщепление неизбежно (хотя вы можете отключить globbing), поскольку getopt
использует пробелы для разделения аргументов. Проблема с getopt
в том, что вывод неоднозначен: нет способа отличить пробел, который был в аргументе, от пробела, который getopt
добавил в качестве разделителя.
Правильный способ сделать это - getopts
. Он надежен и переносим.
while getopts optstring OPTLET; do
# We got the option -$OPTLET
case $OPTLET in
…
esac
done
shift $((OPTIND-1))
# Now the positional parameters are just the non-option operands
¹ По крайней мере, в версии BSD. Версия GNU добавляет возможности, которые делают ее удобной для использования.
Хотя мне кажется странным, что вы сравниваете переменную с чем-то, что вы только что установили, основная проблема заключается в том, что вы используете числовой оператор сравнения (-ne)
для того, что ожидается. быть именем файла (текста ). Вместо этого используйте:
if [ "$filename" != "$1" ]
... где я также процитировал ваши переменные .
Бонус указывает на комментарий steeldriver , который побудил меня изучить это немного глубже.
Основываясь на моем тестировании, я считаю, что ksh видитne
числовой оператор сравнения и выполняет цикл переменного и арифметического расширения двух операндов $filename
и $1
. Таким образом, $filename
превращается в test.txt
, который ksh распознает как возможный compound variable
. Поскольку test
не установлен, вы получаете сообщение об ошибке test.txt: no parent
.