cdのラッパーを書くときにcd“ $ 1”の代わりにcd“ $ @”を使用する必要があるのはなぜですか?


25

他の場所では、次のようにcd関数を見ました:

cd()
{
 builtin cd "$@"
}

$@代わりに使用することが推奨されるのはなぜ$1ですか?

テストディレクトリ「r st」を作成し、この関数を含むスクリプトを呼び出しましたが、どちらの方法でも機能しました

$ . cdtest.sh "r st"

しかし、 $ . cdtest.sh r st私が使用するかどうか失敗しました"$@""$1"


1
cd "$*"また、1つ以上の引数では正しく動作しません。
GoFundMonica-codidact.org

回答:


57

なぜなら、によれば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"


19

を使用"$@"すると、すべての引数がcdwhereに$1渡されます。asは最初の引数のみを渡します。

あなたの例では

$ . cdtest.sh "r st"

1つの引数のみを渡すように常に動作しますが、次のようなフラグも渡す場合

$ . cdtest.sh -L "r st"

その後、ディレクトリが完全に失われるまで拡張される"$@"場合にのみ、正しく実行されます。"$1"cd -L

しかしながら

$ . cdtest.sh r st

2つのパラメーターをcdに渡すため、どちらの場合も失敗しますがrstこれはcdを実行する有効な方法ではありません。パラメーターはスペースで区切られます。スペースは、最初の例のように引用符で囲むかr\ st、1つの引数として扱うためにエスケープする必要があります()。

フラグを渡すことは非常にまれである、あなたはどちらかの現実世界での使用の違いは表示されませんので、あなたが複数のディレクトリに渡すことはできませんが、CDの場合"$1"または"$@"CDのために。しかし、他のコマンドのためにあなたがします、常に使用することをお勧めしますので、違いに気付く"$@"あなたは、このようなラッパー関数やスクリプトを作成する場合。


14

引数がない場合もあります。

$ 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 ""
||

やや無関係ですが、:へのnull引数cdが良いことである理由がついにわかりました。ホームディレクトリに変更する代わりにエラーが発生します。他のいくつかのコマンド、特にrsync、最初の引数がnullの場合、予期しない動作が発生します(転送のソースに現在のディレクトリが含まれます)。
ジョー

4

bashスクリプトの引数はスペースで区切られています。$ 1は最初の引数です。あなたの例では...

例1では、$ 1はストリング "r st" ...です。2番目の例では、$ 1は1文字ストリング 'r' ...です。

$ @はすべての引数です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.