• shell脚本命令行参数 | while getopts


    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    参数列表':a:b:c:h 解释:

    • OPTARG表示选项值,OPTIND表示参数索引位置。
      • 输入命令 cmd -a 1。 此时命中a选项,那么OPTIND为3,表示当前在第三个参数位置。
      • 命令cmd -a 1 -b 2 。同理,当命中a之后,命中b时,OPTIND为5,表示当前在第五个参数位置。
    • a后面有:,表示该选项需要参数,h后面没有:,表示不需要参数。如果是可选参数,跟 “::” 。

    注意

    • 这里第一个:表示,使用抑制错误报告模式。
      • 该模式在识别到无效选项时,会命中?,且当前选项字符会保存在OPTARG中。
      • 在识别到需要参数的选项,没有携带参数时,会命中:,且当前选项字符会保存在OPTARG中。
    逻辑参数:参数列表【abc:d:】
    - copy -x 
    	- 命中“?”, OPTARG被设置为x
    - copy -c 	# 没有指定c的参数
    	-  命中 “:”,OPTARG被设置为c
    
    • 1
    • 2
    • 3
    • 4
    • 5

    程序演示:
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107

    在这里插入图片描述
    需要注意的是,如果源文件是一个目录我们应该怎样操作。(这里提供了 -r 参数,用户手动确认会对目录进行拷贝时,才进行该操作)
    在这里插入图片描述

  • 相关阅读:
    数据结构八:二叉搜索树,Map,Set,哈希
    GOPS·2023上海站 | 提前剧透!阿里、腾讯、字节、擎创等专家齐聚上海,共话互联网运维
    经典算法之直接插入排序(DirectInsert Sort)
    CUDA和cuDNN安装配置
    【OpenCV】多版本那是interesting
    java枚举中写抽象方法
    创新案例分享 | 医院DRG系统建设项目,助力精细化分析医疗数据
    C#子线程操作UI线程更新报线程间操作无效
    英伟达的AI霸主地位会持久吗?
    报错:npm ERR code EPERM
  • 原文地址:https://blog.csdn.net/weixin_43919932/article/details/126201494