bash内置的getopts工具了,用于解析shell脚本中的参数。
格式如下:
# 代码格式参考的这篇文章:https://cloud.tencent.com/developer/article/1629932
#!/usr/bin/bash
while getopts ":a:b:h" opt_arg
do
case "$opt_arg" in
"a")
echo "参数 -a,值 $OPTARG"
;;
"b")
echo "参数 -b ,值 $OPTARG"
;;
"h")
echo "参数 -h,无值"
;;
":")
echo "-$OPTARG 选项需要指定其value值"
;;
"?")
echo "不支持 -$OPTARG 选项"
;;
*)
echo "Unknown error while processing options"
;;
esac
echo "option index is $OPTIND"
done
参数列表':a:b:c:h
解释:
注意:
:
表示,使用抑制错误报告模式。
?
,且当前选项字符会保存在OPTARG中。:
,且当前选项字符会保存在OPTARG中。逻辑参数:参数列表【abc:d:】
- copy -x
- 命中“?”, OPTARG被设置为x
- copy -c # 没有指定c的参数
- 命中 “:”,OPTARG被设置为c
程序演示:
1.正常输出所有值:
2.不带选项。注意这里不带选项是检测不到的。可以利用这个特性,实现省略选项直接使用命令的功能。
3.不在参数列表的选项,命中“?”
4.需要参数的选项没有带参数,命中“:”
除此之外,还可以使用长参数。跟高级的用法可以参考此文章:https://www.cnblogs.com/f-ck-need-u/p/9758075.html
实战演练:
写一个从安卓手机上传文件到pc上的脚本。代码参考如下:
#!/bin/bash
srcPath=/sdcard/DCIM/Camera/
srcFile=$(adb shell ls -ltr $srcPath | tail -n 1 | tr ' ' '\n' | tail -n 1 )
dstPath=$(pwd)/
dstFile=
bool=false # 是否使用了opt参数。没使用就走默认流程
is_opt_r=false # 是否开启递归,这表示拷贝的可能是个目录文件
# 输出提示内容的字符串
Helper(){
echo "使用说明:"
echo " -f 指定源文件名(安卓/sdcard/DICM/目录下)"
echo " -F 指定源文件的路径(不能与-f 一起使用)"
echo " -o 指定存放的文件名(PC当前脚本所在目录下)"
echo " -O 指定存放文件的路径(不能与-O 一起使用)"
echo -e "\n示例参考:"
echo -e " ./copy \t\t\t拷贝 /sdcard/DICM/ 目录下最新生成的文件 到当前脚本所在目录 "
echo -e " ./copy -f xxx.png \t\t拷贝 /sdcard/DICM/xxx.png 文件 到当前脚本所在目录 "
echo -e " ./copy -F /aaa/bbb/xxx.png \t拷贝 /aaa/bbb/xxx.png 文件 到当前脚本所在目录 "
echo -e " ./copy -o file \t\t拷贝 /sdcard/DICM/ 目录下最新生成的文件 到当前脚本所在目录【命名为file】 "
echo -e " ./copy -O /ccc/ddd/file \t拷贝 /sdcard/DICM/ 目录下最新生成的文件 到当前脚本所在目录"
echo -e "\n建议使用以下两种格式:"
echo " eg1: ./copy -f 1.png -o file_1.png"
echo " eg2: ./copy -F sdcard/DCIM/1.png -O /Users/rt/Desktop/file_1.png"
}
Param_error(){ # 参数互斥
echo "参数错误:请检查参数列表"
echo " -f 与 -F 不能同时使用。"
echo " -o 与 -O 不能同时使用。"
exit
}
# f与F互斥,不能同时用
or_op_f=`echo "$*" | grep -Eo '\-f | \-F ' | wc -l`
[ "$or_op_f" -eq 2 ] && Param_error
# o与O互斥,不能同时用
or_op_o=`echo "$*" | grep -Eo '\-o | \-O ' | wc -l`
[ "$or_op_o" -eq 2 ] && Param_error
while getopts ":f:F:o:O:rh" opt_arg
do
bool=true
case "$opt_arg" in
"f")
srcFile=$OPTARG
#echo "set | srcFile name : $srcFile"
;;
"F")
srcPath=""
srcFile=$OPTARG
#echo "set | srcPath/srcFile name : $srcFile"
;;
"o")
dstFile=$OPTARG
#echo "set | dstFile name : $dstFile"
;;
"O")
dstPath=""
dstFile=$OPTARG
#echo "set | dstPath/dstFile name : $dstFile"
;;
"r")
is_opt_r=true
;;
"h")
Helper && exit
;;
":")
echo "请添加$OPTARG的参数"
;;
"?")
echo "参数错误!!"
;;
*)
echo "Unknown error while processing options"
;;
esac
done
if [ "$bool" != "true" ]; then
if [ -n "$1" ]; then
secFile=$1
if [ -n "$2" ]; then
dstFile=$2
fi
fi
fi
# 检查安卓端源文件是否为目录
is_dir="$(adb shell [ -d "$srcPath$srcFile" ] && echo "true")"
# 源文件是否为目录
if [ "$is_dir" == "true" ] && [ "$is_opt_r" == "false" ]; then
echo "error: $fsrcPath$srcFile 是一个目录"
echo " 对目录操作,请使用 -r 参数,进行递归拷贝"
exit
fi
echo "adb pull $srcPath$srcFile $dstPath$dstFile"
adb pull $srcPath$srcFile $dstPath$dstFile
需要注意的是,如果源文件是一个目录我们应该怎样操作。(这里提供了 -r 参数,用户手动确认会对目录进行拷贝时,才进行该操作)