Pourquoi dois-je utiliser le cd «$ @» au lieu du cd «$ 1» lors de l'écriture d'un wrapper pour cd?

25

Ailleurs, j'ai vu une fonction cd comme ci-dessous:

cd()
{
 builtin cd "$@"
}

pourquoi est-il recommandé d'utiliser à la $@place de $1?

J'ai créé un répertoire de test "r st" et appelé le script contenant cette fonction et cela a fonctionné de toute façon

$ . cdtest.sh "r st"

mais a $ . cdtest.sh r stéchoué si j'ai utilisé "$@"ou"$1"

Ravi Kumar
la source
1
cd "$*"ne fonctionnera pas non plus correctement avec plus de 1 argument.
GoFundMonica - codidact.org

Réponses:

57

Parce que, selon bash(1), cdprend des arguments

   cd [-L|[-P [-e]] [-@]] [dir]
          Change  the  current  directory to dir.  if dir is not supplied,
          ...

par conséquent, le répertoire peut ne pas être en fait $1car cela pourrait plutôt être une option telle que -Lou un autre indicateur.

Est-ce grave?

$ cd -L /var/tmp
$ pwd
/var/tmp
$ cd() { builtin cd "$1"; }
$ cd -L /var/tmp
$ pwd
/home/jhqdoe
$ 

Les choses pourraient mal tourner si vous ne vous retrouvez pas là où vous vous attendez à utiliser cd "$1"

branler
la source
19

L'utilisation "$@"passera tous les arguments à cdoù as$1 ne passera que le premier argument.

Dans vos exemples

$ . cdtest.sh "r st"

fonctionne toujours car vous ne passez qu’un seul argument, mais si vous deviez également passer un indicateur tel que

$ . cdtest.sh -L "r st"

Ensuite, seul "$@"s'exécutera correctement où "$1"se développera pour cd -Lperdre entièrement le répertoire.

toutefois

$ . cdtest.sh r st

Ne parvient pas dans les deux cas que vous passez deux paramètres au CD, ret stqui n'est pas un moyen valable pour exécuter cd. Les paramètres sont séparés par des espaces qui doivent être entre guillemets (comme dans votre premier exemple) ou escaped ( r\ st) pour être traités comme un seul argument.

Dans le cas de cd, cependant, il est très rare de passer des drapeaux et vous ne pouvez pas passer dans plusieurs répertoires, vous ne verrez donc pas la différence dans une utilisation réelle de l'un "$1"ou de l'autre "$@"pour le cd. Mais pour d' autres commandes que vous aurez remarqué une différence il est donc préférable d'utiliser toujours "$@"lorsque vous souhaitez créer une fonction d'emballage ou d'un script comme celui - ci.

Michael Daffin
la source
14

Il y a aussi le cas quand il n'y a pas d' arguments:

$ cd /tmp; cd; pwd
/home/muru
$ cd_func() { builtin cd "$1"; }
$ cd_func /tmp; cd_func; pwd
/tmp

cdsans aucun argument, modification du répertoire personnel. Sans aucun argument, se "$@"développe à rien, mais se "$1"développe à la chaîne vide. Ce sont différents:

$ args() { for i in "$@"; do echo "|$i|"; done; }
$ args
$ args ""
||
muru
la source
Un peu sans rapport, mais: je comprends enfin pourquoi un argument nul cdest une bonne chose. Il provoque une erreur au lieu de passer au répertoire personnel. Avec certaines autres commandes, notamment rsync, un premier argument nul provoque un comportement inattendu (inclut le répertoire courant dans les sources du transfert).
Joe
4

Les arguments d'un script bash sont séparés par des espaces. $ 1 est le premier argument. Dans vos exemples ...

Dans l'exemple 1, $ 1 est la chaîne "r st" ... dans le deuxième exemple, $ 1 est la chaîne de caractères "r" ...

$ @ est tous les arguments.

RubberStamp
la source