在其他地方我看到了一个 cd 函数,如下所示:
cd()
{
builtin cd "$@"
}
为什么建议使用$@
而不是$1
?
我创建了一个测试目录“r st”并调用包含此函数的脚本,它可以以任何方式工作
$ . cdtest.sh "r st"
但 $ . cdtest.sh r st
无论我使用"$@"
还是失败"$1"
答案1
因为,根据bash(1)
,cd
接受参数
cd [-L|[-P [-e]] [-@]] [dir]
Change the current directory to dir. if dir is not supplied,
...
因此,该目录实际上可能不存在,$1
因为它可能是一个选项,例如-L
或另一个标志。
这有多糟糕?
$ cd -L /var/tmp
$ pwd
/var/tmp
$ cd() { builtin cd "$1"; }
$ cd -L /var/tmp
$ pwd
/home/jhqdoe
$
如果您最终没有达到预期的使用效果,事情可能会变得非常糟糕cd "$1"
……
答案2
using"$@"
会将所有参数传递到cd
as$1
只会传递第一个参数。
在你的例子中
$ . cdtest.sh "r st"
总是有效,因为您只传递一个参数,但如果您还要传递一个标志,例如
$ . cdtest.sh -L "r st"
然后只有在扩展至完全丢失目录的"$@"
情况下才能正确执行。"$1"
cd -L
然而
$ . cdtest.sh r st
这两种情况都会失败,因为您将两个参数传递给 cd,r
而st
这不是执行 cd 的有效方法。参数由空格分隔,必须用引号引起来(如第一个示例中所示)或转义 ( r\ st
) 才能将其视为一个参数。
然而,在 cd 的情况下,传递标志是非常罕见的,并且您不能传递多个目录,因此您不会看到现实世界中使用或"$1"
的差异"$@"
。但对于其他命令你将要"$@"
请注意差异,因此当您想要创建这样的包装函数或脚本时,最好始终使用它。
答案3
还有这样的情况,当有不参数:
$ cd /tmp; cd; pwd
/home/muru
$ cd_func() { builtin cd "$1"; }
$ cd_func /tmp; cd_func; pwd
/tmp
cd
不带任何参数更改主目录。如果没有任何参数,则"$@"
扩展为空,但"$1"
扩展为空字符串。这些是不同的:
$ args() { for i in "$@"; do echo "|$i|"; done; }
$ args
$ args ""
||
答案4
bash 脚本的参数以空格分隔。 $1 是第一个参数。在你的例子中...
在示例 1 中,$1 是字符串“r st”...在第二个示例中,$1 是单字符字符串“r”...
$@ 是所有参数。