如何在 Linux 中使用终端命令将文件参数传递给我的 bash 脚本? [复制]
Posted
技术标签:
【中文标题】如何在 Linux 中使用终端命令将文件参数传递给我的 bash 脚本? [复制]【英文标题】:How can I pass a file argument to my bash script using a Terminal command in Linux? [duplicate] 【发布时间】: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)
如何通过我的程序实现这一点?
【问题讨论】:
【参考方案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"
另见:
“规范”示例:http://software.frodo.looijaard.name/getopt/docs/getopt-parse.bash 一篇博文:http://www.missiondata.com/blog/system-administration/17/17/man getopt
链接失效。这里来自互联网档案:
https://web.archive.org/web/20100325015445/http://software.frodo.looijaard.name/getopt/docs/getopt-parse.bash
https://web.archive.org/web/20130827004301/http://www.missiondata.com/blog/system-administration/17/17/
【讨论】:
【参考方案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 用于引用。但是getopt
和getopts
都不能解析 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:好点。谢谢!以上是关于如何在 Linux 中使用终端命令将文件参数传递给我的 bash 脚本? [复制]的主要内容,如果未能解决你的问题,请参考以下文章