How to Pass Parameters to a Bash Script

How to pass all arguments passed to my Bash script to a function of mine?

The $@ variable expands to all command-line parameters separated by spaces. Here is an example.

abc "$@"

When using $@, you should (almost) always put it in double-quotes to avoid misparsing of arguments containing spaces or wildcards (see below). This works for multiple arguments. It is also portable to all POSIX-compliant shells.

It is also worth noting that $0 (generally the script's name or path) is not in $@.

The Bash Reference Manual Special Parameters Section says that $@ expands to the positional parameters starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is "$@" is equivalent to "$1" "$2" "$3"....

Passing some arguments:

If you want to pass all but the first arguments, you can first use shift to "consume" the first argument and then pass "$@" to pass the remaining arguments to another command. In Bash (and zsh and ksh, but not in plain POSIX shells like dash), you can do this without messing with the argument list using a variant of array slicing: "${@:3}" will get you the arguments starting with "$3". "${@:3:4}" will get you up to four arguments starting at "$3" (i.e. "$3" "$4" "$5" "$6"), if that many arguments were passed.

Things you probably don't want to do:

"$*" gives all of the arguments stuck together into a single string (separated by spaces, or whatever the first character of $IFS is). This looses the distinction between spaces within arguments and the spaces between arguments, so is generally a bad idea. Although it might be ok for printing the arguments, e.g. echo "$*", provided you don't care about preserving the space within/between distinction.

Assigning the arguments to a regular variable (as in args="$@") mashes all the arguments together like "$*" does. If you want to store the arguments in a variable, use an array with args=("$@") (the parentheses make it an array), and then reference them as e.g. "${args[0]}" etc. Note that in Bash and ksh, array indexes start at 0, so $1 will be in args[0], etc. zsh, on the other hand, starts array indexes at 1, so $1 will be in args[1]. And more basic shells like dash don't have arrays at all.

Leaving off the double-quotes, with either $@ or $*, will try to split each argument up into separate words (based on whitespace or whatever's in $IFS), and also try to expand anything that looks like a filename wildcard into a list of matching filenames. This can have really weird effects, and should almost always be avoided. (Except in zsh, where this expansion doesn't take place by default.)

Bash script passing parameter with spaces using variables

You should change CMD="curl -H $HEADER $URL" in CMD="curl -H \"$HEADER\" \"$URL\"".

Propagate all arguments in a Bash shell script

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

Observe:

$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $@

$ cat quotes.sh
#!/bin/bash
echo_args.sh "$@"

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

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

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

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

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

Is there a way to pass the parameters within the script in bash?

From what I understand, the program is asking you to type those parameters, because it won't read them as command line arguments. If that is the case, you could try to read from a file (but there's a better option!) like this in your script.sh:

#!/bin/bash
simulationProgram < fileWithArguments.txt

The file "fileWithArguments.txt" should have every argument the program is asking you to type, one per line and in the order the program asks them.

About the better way? Use a heredoc, it's like putting a file inside a file:

#!/bin/bash
simulationProgram << EOF
argument1
...
lastArgument
EOF

anotherCommands # If you need them

The EOF tells bash where the here-doc ends, you can use any word, but be sure that the one after << and at the end of the arguments are the same. You can also use bash variables inside the here-doc.

EDIT: I wasn't as clear as I should have been. The heredoc should go in the script with the loop, not in the bash call. Here is what your script should look like, assuming it only asks for 1.24 and 1 each time you run the program (note that 1.24 and 1 are in different lines):

#!/bin/bash
name="Na"
for j in {1..3}
do
mkdir $j
cd $j
../../../../../abcinp "$name$j" 1 LennardJones 5.0 30 300 5 30 $j Na << EOF
1.24
1
EOF

cd ../
done

echo "All done"

What happens inside:

  1. The name variable gets initialized.
  2. The loop starts, j is 1.
  3. You create the dir $j (so it will be called "1")
  4. You go to that directory.
  5. You launch abcinp, which I assume calculates a molecular parameter or something (this physics program all have the annoying habit of asking for manual input), with a series of arguments.
  6. abcinp launchs, and asks for manual input.
  7. Bash answers the manual input with the first line after "EOF": 1.24.
  8. Bash does the same the second time asks for manual input, with the second line (so it will answer 1).
  9. Then the program stops asking for parameters and starts calculating. When it finish, you move to the parent directory and start with the next iteration of the loop. After all of them are done, echo will print "All done".

Note: I'm assuming abcinp asks for a parameter, then you press enter, and then asks for another one. If you literally have to type "1.24 1" in the same line, they should be in the same line in your script.

Can't pass parameters to bash script from zsh

Replace "@a" by "$1" for only first parameter or "${@}" for all parameters

How to pass Named Parameter in Shell Script

You may want to read the getopts manual page


while getopts "U:P:J:I:" flag
do
case "${flag}" in
U) TEST_USER=${OPTARG};;
P) TEST_PWD=${OPTARG};;
J) TEST_JOBID=${OPTARG};;
I) TEST_PROJECTID=${OPTARG};;
esac
done
echo "USER: $TEST_USER";
echo "PWD: $TEST_PWD";
echo "JOBID: $TEST_JOBID";
echo "PROJECTID: $TEST_PROJECTID";
./getopts.sh -U devops@gmail.com -P xxxxxx -J 8a809e2496 -I 80e2ea54b231f
USER: devops@gmail.com
PWD: xxxxxx
JOBID: 8a809e2496
PROJECTID: 80e2ea54b231f

With getopt, it's more complicated, but it allows long options and "=".

    #!/bin/bash
TEMP=$(getopt -n "$0" -a -l "user:,password:,jobid:,projectid:" -- -- "$@")

[ $? -eq 0 ] || exit

eval set -- "$TEMP"

while [ $# -gt 0 ]
do
case "$1" in
--user) TEST_USER="$2"; shift;;
--password) TEST_PWD="$2"; shift;;
--jobid) TEST_JOBID="$2"; shift;;
--projectid) TEST_PROJECTID="$2"; shift;;
--) shift;;
esac
shift;
done
echo "USER: $TEST_USER";
echo "PWD: $TEST_PWD";
echo "JOBID: $TEST_JOBID";
echo "PROJECTID: $TEST_PROJECTID";

Some tests:

$ ./test.sh -user=jules -password=kabas -jobid 5555 -projectid 999 -c
./test.sh: unrecognized option '-c'

$ ./test.sh -user=jules -password=kabas -jobid 5555 -projectid 999
USER: jules
PWD: kabas
JOBID: 5555
PROJECTID: 999

How to pass parameters using command line arguments in shell script

Since read reads from stdin, you need to pass the filenames on stdin:

{ echo "file.jmx"; echo "file.jtl"; } | ./script.sh start

Using a here-document can be tidier:

./script.sh start <<END_INPUT
file.jmx
file.jtl
END_INPUT

A bit of code review: if the usage only takes a single parameter, "start" or "stop", you don't need the while loop:

#!/bin/sh

do_start_stuff() { ... }
do_stop_stuff() { ... }

case "$1" in
start) do_start_stuff;;
stop) do_stop_stuff;;
*) echo "Usage: $0 {start|stop}"; exit 1;;
esac

To rewrite your script to take all the parameters:

#!/bin/sh

usage() {
echo "Usage $0 {start ...|stop}"
# provide more info about arguments for the start case
# provide an example usage
}

case "$1" in
stop) do_stop_stuff ;;
start)
shift
if [ "$#" -ne 4 ]; then usage; exit 1; fi
jmeter.sh -n -t "$1" "$2" -l "$3" "$4"
;;
*) usage ;;
esac

Passing parameters to a Bash function

There are two typical ways of declaring a function. I prefer the second approach.

function function_name {
command...
}

or

function_name () {
command...
}

To call a function with arguments:

function_name "$arg1" "$arg2"

The function refers to passed arguments by their position (not by name), that is $1, $2, and so forth. $0 is the name of the script itself.

Example:

function_name () {
echo "Parameter #1 is $1"
}

Also, you need to call your function after it is declared.

#!/usr/bin/env sh

foo 1 # this will fail because foo has not been declared yet.

foo() {
echo "Parameter #1 is $1"
}

foo 2 # this will work.

Output:

./myScript.sh: line 2: foo: command not found
Parameter #1 is 2

Reference: Advanced Bash-Scripting Guide.



Related Topics



Leave a reply



Submit