Propagate all arguments in a bash shell script

2019-01-20 07:16发布

问题:

I am writing a very simple script that calls another script, and I need to propagate the parameters from my current script to the script I am executing.

For instance, my script name is foo.sh and calls bar.sh

foo.sh:

bar $1 $2 $3 $4

How can I do this without explicitly specifying each parameter?

回答1:

Use "$@" instead of plain $@ if you actually wish your parameters to be passed the same.

Observe:

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


回答2:

For bash and other Bourne-like shells:

java com.myserver.Program "$@"


回答3:

Use "$@" (works for all POSIX compatibles).

[...] , bash features the "$@" variable, which expands to all command-line parameters separated by spaces.

From Bash by example.



回答4:

#!/usr/bin/env bash
while [ "$1" != "" ]; do
  echo "Received: ${1}" && shift;
done;

Just thought this may be a bit more useful when trying to test how args come into your script



回答5:

I realize this has been well answered but here's a comparison between "$@" $@ "$*" and $*

Contents of test script:

# 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 "================================="

Now, run the test script with various 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
=================================


回答6:

My SUN Unix has a lot of limitations, even "$@" was not interpreted as desired. My workaround is ${@}. For example,

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

By the way, I had to have this particular script because my Unix also does not support grep -r



回答7:

Works fine, except if you have spaces or escaped characters. I don't find the way to capture arguments in this case and send to a ssh inside of script.

This could be useful but is so ugly

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


回答8:

If you include $@ in a quoted string with other characters the behavior is very odd when there are multiple arguments, only the first argument is included inside the quotes.

Example:

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

Yields:

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

But assigning to a different variable first:

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

Yields:

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