为什么在编写 cd 的包装器时需要使用 cd "$@" 而不是 cd "$1" ?

为什么在编写 cd 的包装器时需要使用 cd "$@" 而不是 cd "$1" ?

在其他地方我看到了一个 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"$@"会将所有参数传递到cdas$1只会传递第一个参数。

在你的例子中

$ . cdtest.sh "r st"

总是有效,因为您只传递一个参数,但如果您还要传递一个标志,例如

$ . cdtest.sh -L "r st"

然后只有在扩展至完全丢失目录的"$@"情况下才能正确执行。"$1"cd -L

然而

$ . cdtest.sh r st

这两种情况都会失败,因为您将两个参数传递给 cd,rst这不是执行 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”...

$@ 是所有参数。

相关内容