Perché devo usare cd “$ @” invece di cd “$ 1” quando scrivo un wrapper per cd?


25

Altrove ho visto una funzione cd come di seguito:

cd()
{
 builtin cd "$@"
}

perché si consiglia di utilizzare $@anziché $1?

Ho creato una directory di test "r st" e chiamato lo script contenente questa funzione e ha funzionato in entrambi i modi

$ . cdtest.sh "r st"

ma $ . cdtest.sh r stho fallito se ho usato "$@"o"$1"


1
cd "$*"inoltre non funzionerà correttamente con più di 1 arg.
GoFundMonica - codidact.org,

Risposte:


57

Perché, secondo bash(1), cdaccetta argomenti

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

quindi la directory in realtà potrebbe non essere in $1quanto potrebbe invece essere un'opzione come -Lo un'altra bandiera.

Quanto è grave?

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

Le cose potrebbero andare molto male se non finissi dove ti aspetti di usare cd "$1"...


19

L'utilizzo "$@"passerà tutti gli argomenti a cddove as $1passerà solo il primo argomento.

Nei tuoi esempi

$ . cdtest.sh "r st"

funziona sempre come si passa solo in un argomento, ma se si dovesse passare anche una bandiera come

$ . cdtest.sh -L "r st"

Quindi "$@"verrà eseguito correttamente solo dove "$1"si espanderà per cd -Lperdere completamente la directory.

tuttavia

$ . cdtest.sh r st

Non riesce in entrambi i casi quando si passano due parametri su cd re stquesto non è un modo valido per eseguire cd. I parametri sono separati da spazi che devono essere quotati (come nel tuo primo esempio) o escape ( r\ st) per essere trattati come un argomento.

Nel caso del cd, tuttavia, è molto raro passare in flag e non è possibile passare in più directory in modo da non vedere la differenza nell'uso reale di uno "$1"o "$@"di cd. Ma per gli altri comandi che si nota una differenza quindi è meglio la pratica di usare sempre "$@"quando si desidera creare una funzione wrapper o script come questo.


14

C'è anche il caso in cui non ci sono nessun argomenti:

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

cdsenza alcun argomento cambia nella home directory. Senza alcun argomento, si "$@"espande a nulla, ma si "$1"espande nella stringa vuota. Questi sono diversi:

$ args() { for i in "$@"; do echo "|$i|"; done; }
$ args
$ args ""
||

Un po 'estraneo, ma: finalmente capisco perché un argomento nullo cdè una buona cosa. Causa un errore invece di passare alla home directory. Con alcuni altri comandi, in particolare rsync, un primo argomento nullo provoca un comportamento imprevisto (include la directory corrente nelle origini del trasferimento).
Joe,

4

Gli argomenti di uno script bash sono delimitati da spazi. $ 1 è il primo argomento. Nei tuoi esempi ...

Nell'esempio 1, $ 1 è la stringa "r st" ... nel secondo esempio, $ 1 è la stringa di un carattere "r" ...

$ @ sono tutti gli argomenti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.