CD用のラッパーを作成するときにcd "$1"の代わりにcd "$@"を使用するのはなぜですか?

CD用のラッパーを作成するときにcd "$1"の代わりにcd "$@"を使用するのはなぜですか?

他の場所では、次の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

を使用すると、"$@"すべてのパラメータがcdasに渡され、$1最初のパラメータのみが渡されます。

あなたの例では

$ . cdtest.sh "r st"

1つのパラメータだけを渡すので常に機能しますが、フラグも渡す場合(例:

$ . cdtest.sh -L "r st"

これにより、ディレクトリが完全に欠落している状態に展開された"$@"場合にのみ正しく実行されます。"$1"cd -L

しかし、

$ . cdtest.sh r st

両方の引数をcdに渡すので、どちらの場合も失敗します。rこれはstcd を実行する有効な方法ではありません。パラメータはスペースで区切られ、1つ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"です... 2番目の例では、$ 1は単一の文字列 "r"です...

$ @はすべてパラメータです。

関連情報