【问题标题】:How can I pass a file argument to my bash script using a Terminal command in Linux? [duplicate]如何在 Linux 中使用终端命令将文件参数传递给我的 bash 脚本? [复制]
【发布时间】:2011-04-01 20:20:36
【问题描述】:

所以我的问题是如何在 Linux 中使用终端命令将文件参数传递给我的 bash 脚本? 目前我正在尝试用 bash 制作一个程序,该程序可以从终端获取文件参数并将其用作程序中的变量。例如我跑 myprogram --file=/path/to/file 在终端中。

我的程序

#!/bin/bash    
File=(the path from the argument)  
externalprogram $File (other parameters)

如何通过我的程序实现这一点?

【问题讨论】:

    标签: linux bash shell command-line terminal


    【解决方案1】:

    您可以使用 getopt 来处理 bash 脚本中的参数。 getopt 的解释并不多。这是一个例子:

    #!/bin/sh
    
    OPTIONS=$(getopt -o hf:gb -l help,file:,foo,bar -- "$@")
    
    if [ $? -ne 0 ]; then
      echo "getopt error"
      exit 1
    fi
    
    eval set -- $OPTIONS
    
    while true; do
      case "$1" in
        -h|--help) HELP=1 ;;
        -f|--file) FILE="$2" ; shift ;;
        -g|--foo)  FOO=1 ;;
        -b|--bar)  BAR=1 ;;
        --)        shift ; break ;;
        *)         echo "unknown option: $1" ; exit 1 ;;
      esac
      shift
    done
    
    if [ $# -ne 0 ]; then
      echo "unknown option(s): $@"
      exit 1
    fi
    
    echo "help: $HELP"
    echo "file: $FILE"
    echo "foo: $FOO"
    echo "bar: $BAR"
    

    另见:

    链接失效。这里来自互联网档案:

    【讨论】:

      【解决方案2】:

      如果你只是运行你的脚本会更容易(而且更“正确”,见下文)

      myprogram /path/to/file
      

      然后您可以以$1 的形式访问脚本中的路径(对于参数#1,类似地$2 是参数#2,等等)

      file="$1"
      externalprogram "$file" [other parameters]
      

      或者只是

      externalprogram "$1" [otherparameters]
      

      如果你想从--file=/path/to/file 之类的东西中提取路径,通常使用getopts shell 函数来完成。但这比仅仅引用$1 更复杂,此外,像--file= 这样的开关是可选的。我猜你的脚本需要提供一个文件名,所以在选项中传递它是没有意义的

      【讨论】:

      • 请注意,所有参数扩展都必须引用,包括$file
      • 有没有办法实现 --file 方法?我想这样做是因为如果它在没有 --file 参数的情况下运行,程序可能会询问用户应该选择哪个文件。它将以这种方式简化程序。
      • 通常只检查用户是否提供了文件名(参数# 包含位置参数的数量),如果没有给出文件或-,则使用标准输入。如果您想要--file= 语法,请使用case 语句。
      • @Philipp(3 cmets up):这取决于您希望如何解释它们。但在这种情况下,这可能是有道理的——我只是不小心错过了一个。我会编辑它。
      • 文件名中有空格怎么办?
      【解决方案3】:

      假设您按照 David Zaslavsky 的建议进行操作,因此第一个参数只是 要运行的程序(不需要选项解析),您正在处理如何传递参数 2 的问题并转到您的外部程序。这里有一个方便的方法:

      #!/bin/bash
      ext_program="$1"
      shift
      "$ext_program" "$@"
      

      shift 将删除第一个参数,重命名其余参数($2 变为 $1, and so on).$@` 指的是参数,作为一个单词数组(它必须被引用!)。

      如果你必须有你的--file 语法(例如,如果有一个默认程序要运行,那么用户不必提供一个),只需将ext_program="$1" 替换为你对$1 的任何解析需要做的,也许使用 getopt 或 getopts。

      如果您想自己动手,仅针对一种特定情况,您可以执行以下操作:

      if [ "$#" -gt 0 -a "${1:0:6}" == "--file" ]; then
          ext_program="${1:7}"
      else
          ext_program="default program"
      fi
      

      【讨论】:

      • +1 用于引用。但是getoptgetopts 都不能解析 GNU 风格的参数。
      • @Philipp:getopts 不能,但 getopt 绝对可以,无论如何在我的系统上。这大概是因为有 GNU 和非 GNU 版本的 C 函数 getopt
      【解决方案4】:

      Bash 支持称为“位置参数”的概念。这些位置参数表示调用 Bash 脚本时在命令行上指定的参数。

      位置参数由名称$0$1$2...等引用。 $0 是脚本本身的名称,$1 是脚本的第一个参数,$2 第二个等等。$* 代表所有位置参数,除了$0(即以@ 开头) 987654329@)。

      一个例子:

      #!/bin/bash
      FILE="$1"
      externalprogram "$FILE" <other-parameters>
      

      【讨论】:

      • 是的,你是对的,在这种情况下,我们希望$1 包含一个文件名,如果文件名包含一个或多个空格,则应该引用它以避免分词。但是引用位置参数总是有必要吗?
      • 我认为总是引用所有变量比猜测它们是否必须被引用更容易。位置参数是用户输入,用户可以输入任何内容,因此除非记录了参数经历了分词,否则必须引用它。从技术上讲,变量不必在= 之后和[[...]] 内引用,但引用它们比记住不执行分词的位置更容易。
      • @Philipp:好点。谢谢!
      猜你喜欢
      • 1970-01-01
      • 2013-10-11
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 2015-02-05
      • 2011-04-18
      相关资源
      最近更新 更多