我正在开始一个项目,涉及从命令行获取文件名作为参数。我在其他地方找不到任何有关它的信息。我还没有代码,因为这是我的第一步。
预先感谢您的任何帮助。我会在这里积极尝试您可能有的任何建议
答案1
寻址位置参数
首先让我们澄清一些事情:当引用 bash 脚本时,命令行参数称为“位置参数”,即、$1
等变量。这就是我将在这里使用的词汇。$2
$3
根据正确的 shell 语法,位置参数出现在命令之后(显然,有些人可能会说废话,但语法很重要):
command a b c
假设command
是你的脚本my_script.sh
。从脚本中,您可以对参数执行单独的命令,如echo $1
和echo $2
。您还可以从事全部通过 for 循环立即获得它们。例如,您的简单脚本可能如下所示:
#!/bin/sh
# Note important difference between /bin/sh and /bin/bash
# https://askubuntu.com/q/141928/295286
echo "$1"
# for loop will substitute each $1, $2,$3 value into i each time
for i
do
echo "$i"
done
寻址文件名部分
位置参数可以是任何东西(数字或文本)这一事实将其解释留给了脚本作者。如果文本字符串是文件名,那么它自然必须存在于文件系统上的某个位置(与匿名文件、管道或套接字不同[需要在此处引用])。
假设您调用脚本,因为my_script "this_is_my_file.txt". Simple way to test whether
this_is_my_file.txt` 是现有文件名:
test -f "$1"
或者
[ -f "$1" ]
为什么 ?$1
因为它是第一个位置参数。为什么test
或[
?因为这是同一个命令。从那里你可以使用它
if [ -f "$1" ]; then
echo "$1" exists
fi
或者
[ -f "$1" ] && echo "$1" exists
当然,对于一个好的脚本来说,如果文件不存在,则发出错误并让脚本退出。
编写脚本的重要事项之一是培养自己的习惯。因为您无法预测用户将为脚本指定的文件名,所以它可以是任何文件名,这也意味着它可以以-
.例如,-afilename
。此类文件名通常会破坏必须处理位置参数的脚本和常规命令。如果您期望或特别要求文件名存在在当前工作目录中,最好使用./
before 变量。
if [ -f ./"$1" ]
即使您的用户明确指出./
这仍然有效:
$ test -f ././input.txt && echo "YES"
YES
如果我们处理的文件名还包括文件路径,那不会是问题 - 文件名之前的最后一个斜杠/path/to/-difficult_name.txt
将文件名与路径的其余部分分开。
...稍后编辑和扩展...
答案2
当使用参数调用脚本时,它们将作为参数传递给脚本位置参数。这些参数可以使用$1
, $2
...来调用${10}
,${11}
注意:任何两位数参数都需要括号。
此外,$@
和$*
可用于表示所有参数,其中:
($*) 扩展为位置参数,从 1 开始。当扩展不在双引号内时,每个位置参数都会扩展为一个单独的单词。在执行它的上下文中,这些单词会受到进一步的单词分割和路径名扩展。当扩展发生在双引号内时,它会扩展为单个单词,每个参数的值由 IFS 特殊变量的第一个字符分隔。也就是说,“$*”相当于“$1c$2c…”,其中c是IFS变量值的第一个字符。如果未设置 IFS,则参数之间用空格分隔。如果 IFS 为空,则连接参数时不插入分隔符。
和
($@) 扩展为位置参数,从 1 开始。当扩展发生在双引号内时,每个参数都会扩展为一个单独的单词。也就是说,“$@”相当于“$1”“$2”……。如果双引号扩展发生在单词内,则第一个参数的扩展与原始单词的开头部分连接,最后一个参数的扩展与原始单词的最后部分连接。当没有位置参数时,“$@”和$@ 扩展为空(即,它们被删除)。
这是一个显示此示例的脚本:
脚本
#!/bin/sh
echo "My arguments are $@"
echo "$1 -- $2 -- $3 -- $4 -- $5 -- $6 -- $7 -- $8 -- $9 -- $10"
echo "Correct parameter 10 is ${10}"
在行动
$ ./script one two three four five six seven eight nine ten
My arguments are one two three four five six seven eight nine ten
one -- two -- three -- four -- five -- six -- seven -- eight -- nine -- one0
Correct parameter 10 is ten
Bash 参考手册3.4 外壳参数