一旦 bash 程序在处理 中的选项时执行getops,循环就会退出。
作为一个简短的例子,我有以下 bash 脚本:
#!/usr/bin/env bash
while getopts ":a:l:" opt; do
case ${opt} in
a)
ls -a $2
;;
l)
ls -l $2
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument" >&2
exit 1
;;
esac
done
echo -e "\nTerminated"
Run Code Online (Sandbox Code Playgroud)
如果脚本被调用test.sh,当我用这个命令执行脚本时,我得到以下输出,其中只-a处理标志,并被-l忽略:
$ ./test.sh -al .
. .. file1.txt file2.txt test.sh
Terminated
Run Code Online (Sandbox Code Playgroud)
但是,如果我删除每个参数后的冒号,表示每个参数不需要操作数,那么脚本会按预期执行。如果while循环改为:
while getopts ":al" opt; do
Run Code Online (Sandbox Code Playgroud)
然后,运行我的脚本会给出以下输出(同时处理-a和-l处理):
$ ./test.sh -al .
. .. file1.txt file2.txt test.sh
total 161
-rwxrwxrwx 1 root root 0 Nov 24 22:31 file1.txt
-rwxrwxrwx 1 root root 0 Nov 24 22:32 file2.txt
-rwxrwxrwx 1 root root 318 Nov 24 22:36 test.sh
Terminated
Run Code Online (Sandbox Code Playgroud)
此外,OPTIND=1在我的循环末尾添加类似的内容只会导致脚本执行第一个参数的无限循环。
如何getopts使用选项参数(:在每个参数之后)解析多个参数?
只说短选项,选项和它的参数之间不需要空格,所以-o something等于-osomething。尽管将它们分开是很常见的,但也有一些例外,例如:cut -d: -f1.
就像@AlexP 所说的那样,如果您使用while getopts ":a:l:" opt, 则 options-a并且-l预计会有一个论点。当您传递-al给您的脚本并选择-a需要参数时,getopts查找它并基本上看到这一点:-a l这就是它忽略该-l选项的原因,因为-a“吃了它”。
您的代码有点乱,正如@cdarke 所建议的那样,它没有使用 提供的方法getopts,例如$OPTARG. 您可能想查看此getopts 教程。
如果我理解正确,您的主要目标是检查文件/文件夹是否已传递给ls. 您将不是通过使选项需要参数来实现这一点,而是通过检查所有选项之后是否存在文件/文件夹来实现这一点。你可以使用这个来做到这一点:
#!/usr/bin/env bash
while getopts ":al" opt; do
case ${opt} in
a) a=1 ;;
l) l=1 ;;
\?) echo "Invalid option: -$OPTARG" >&2; exit 1 ;;
:) echo "Option -$OPTARG requires an argument" >&2; exit 1 ;;
esac
done
shift $(( OPTIND - 1 ));
[[ "$#" == 0 ]] && { echo "No input" >&2; exit 2; }
input=("$@")
[[ "$a" == 1 ]] && ls -a "${input[@]}"
[[ "$l" == 1 ]] && ls -l "${input[@]}"
echo Done
Run Code Online (Sandbox Code Playgroud)
此解决方案将您由选项触发的选择保存到变量(您可以使用数组代替),然后根据这些变量做出决定。保存到变量/数组为您提供了更大的灵活性,因为您可以在脚本中的任何位置使用它们。
处理完所有选项后, shift $(( OPTIND - 1 ));所有选项后丢弃所有选项和相关参数,只留下不属于任何选项的参数 = 您的文件/文件夹。如果没有任何文件/文件夹,您会检测到[[ "$#" == 0 ]]并退出。如果有,将它们保存到一个数组中input=("$@"),稍后在决定变量时使用这个数组:
[[ "$a" == 1 ]] && ls -a "${input[@]}"
[[ "$l" == 1 ]] && ls -l "${input[@]}"
Run Code Online (Sandbox Code Playgroud)
此外,与 不同的是ls -a $2,使用数组可以ls -a "${input[@]}"让您传递多个文件/文件夹:./test.sh -la . "$HOME"。