Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass all arguments passed to my bash script to a function of mine? [duplicate]

Let's say I have defined a function abc() that will handle the logic related to analyzing the arguments passed to my script.

How can I pass all arguments my bash script has received to it? The number of params is variable, so I can't just hardcode the arguments passed like this:

abc $1 $2 $3 $4 

Edit. Better yet, is there any way for my function to have access to the script arguments' variables?

like image 297
devoured elysium Avatar asked Sep 28 '10 09:09

devoured elysium


People also ask

How do I pass multiple arguments in bash?

You can pass more than one argument to your bash script. In general, here is the syntax of passing multiple arguments to any bash script: script.sh arg1 arg2 arg3 … The second argument will be referenced by the $2 variable, the third argument is referenced by $3 , .. etc.

How do we pass arguments to function in bash?

To pass any number of arguments to the bash function simply put them right after the function's name, separated by a space. It is a good practice to double-quote the arguments to avoid the misparsing of an argument with spaces in it. The passed parameters are $1 , $2 , $3 …

How do you assign a all the arguments to a single variable?

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.

What is $@ in bash?

bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.


2 Answers

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.)

like image 52
Gordon Davisson Avatar answered Sep 22 '22 02:09

Gordon Davisson


I needed a variation on this, which I expect will be useful to others:

function diffs() {         diff "${@:3}" <(sort "$1") <(sort "$2") } 

The "${@:3}" part means all the members of the array starting at 3. So this function implements a sorted diff by passing the first two arguments to diff through sort and then passing all other arguments to diff, so you can call it similarly to diff:

diffs file1 file2 [other diff args, e.g. -y] 
like image 31
hajamie Avatar answered Sep 18 '22 02:09

hajamie