web-dev-qa-db-fra.com

Propager tous les arguments dans un script bash shell

J'écris un script très simple qui appelle un autre script et j'ai besoin de propager les paramètres de mon script actuel vers le script que j'exécute.

Par exemple, mon nom de script est foo.sh et appelle bar.sh

foo.sh:

bar $1 $2 $3 $4

Comment puis-je faire cela sans spécifier explicitement chaque paramètre?

729
Fragsworth

Utilisez "$@" au lieu de plain $@ si vous souhaitez que vos paramètres soient transmis de la même manière.

Observer:

$ cat foo.sh
#!/bin/bash
baz.sh $@

$ cat bar.sh
#!/bin/bash
baz.sh "$@"

$ cat baz.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4

$ ./foo.sh first second
Received: first
Received: second
Received:
Received:

$ ./foo.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:

$ ./bar.sh first second
Received: first
Received: second
Received:
Received:

$ ./bar.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
1212
Sdaz MacSkibbons

Pour bash et autres coquilles de type Bourne:

Java com.myserver.Program "$@"
463
Chris Johnsen

Utilisez "$@" (fonctionne pour tous les POSIX compatibles).

[...], bash contient la variable "$ @", qui s'étend à tous les paramètres de ligne de commande séparés par des espaces.

De Bash par exemple .

87
miku

Je réalise que cela a été bien répondu mais voici une comparaison entre "$ @" $ @ "$ *" et $ *

Contenu du script de test:

# cat ./test.sh
#!/usr/bin/env bash
echo "================================="

echo "Quoted DOLLAR-AT"
for ARG in "$@"; do
    echo $ARG
done

echo "================================="

echo "NOT Quoted DOLLAR-AT"
for ARG in $@; do
    echo $ARG
done

echo "================================="

echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
    echo $ARG
done

echo "================================="

echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
    echo $ARG
done

echo "================================="

Maintenant, lancez le script de test avec différents arguments:

# ./test.sh  "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
40
JDS
#!/usr/bin/env bash
while [ "$1" != "" ]; do
  echo "Received: ${1}" && shift;
done;

J'ai pensé que cela pourrait être un peu plus utile pour essayer de voir comment les arguments entrent dans votre script

30
Gregory Patmore

Mon Sun Unix a beaucoup de limitations, même "$ @" n'a pas été interprété comme souhaité. Ma solution de contournement est $ {@}. Par exemple,

#!/bin/ksh
find ./ -type f | xargs grep "${@}"

A propos, je devais avoir ce script particulier parce que mon Unix ne supporte pas non plus grep -r

8
Hampden123

Si vous incluez $@ dans une chaîne citée avec d'autres caractères, le comportement est très étrange lorsqu'il existe plusieurs arguments, seul le premier argument est inclus à l'intérieur des guillemets.

Exemple:

#!/bin/bash
set -x
bash -c "true foo $@"

Rendements:

$ bash test.sh bar baz
+ bash -c 'true foo bar' baz

Mais assigner d’abord à une variable différente:

#!/bin/bash
set -x
args="$@"
bash -c "true foo $args"

Rendements:

$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
5
ColinM

Fonctionne bien, sauf si vous avez des espaces ou des caractères échappés. Je ne trouve pas le moyen de capturer des arguments dans ce cas et d'envoyer à un SSH à l'intérieur du script.

Cela pourrait être utile mais est tellement moche

_command_opts=$( echo "$@" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&@",$i) ; gsub(/ $/,"",$i );gsub (/$/,"@",$i) }; print $0 }' | tr '@' \' )
3
user6650302