How to Put All Command Arguments in One Variable

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:

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

How to pass a variable which has multiple arguments to function all at once?

It is not a good idea to store filenames in a string. Storing them in an array is a much better approach:

#!/usr/bin/env bash

[[ $# -lt 2 ]] && exit 1

name=$1; shift
files=("$@")

#exclude all files/directories that are not readable
for index in "${!files[@]}"; do
[[ -r ${files[index]} ]] || unset "files[index]"
done

[[ ${#files[@]} -eq 0 ]] && exit 1

if tar -czvf "${name:-def_$$}.tar.gz" "${files[@]}"; then
echo "Ok"
else
echo "Error"
exit 1
fi

shift; files=("$@") discards the first argument (name) and saves the rest of the arguments (filenames) into an array.


You could also construct the array of filenames for tar with a more straightforward approach:

name=$1; shift

for file; do
[[ -r $file ]] && files+=("$file")
done

I would like to store all command-line arguments to a Bash script into a single variable

echo "$*"

would do what you want, namely printing out the entire command-line arguments, separated by a space (or, technically, whatever the value of $IFS is). If you wanted to store it into a variable, you could do

thevar="$*"

If that doesn't answer your question well enough, I'm not sure what else to say...

BASH store command line arguments as separate variables

They already are stored in a variable: $@. You can access the individual indices as $1, $2, etc. You don't need to store them in new variables if those are sufficient.

# Loop over arguments.
for arg in "$@"; do
echo "$arg"
done

# Access arguments by index.
echo "First = $1"
echo "Second = $2"
echo "Third = $3"

If you do want a new array, args=("$@") will assign them all to a new array in one shot. No need for the explicit for loop. You can then access the individual elements with ${args[0]} and the like.

args=("$@")

# Loop over arguments.
for arg in "${args[@]}"; do
echo "$arg"
done

# Access arguments by index.
echo "First = ${args[0]}"
echo "Second = ${args[1]}"
echo "Third = ${args[2]}"

(Note that using an explicit array the indices start at 0 instead of 1.)

Can't accept multiple command line arguments and assign to variable

When you write char service = argv[2];, you are assigning a char pointer to a char. You know argv is a char pointer array, because you define it as char *argv[]. Fix by just adding char *service = argv[2];

So your rewritten code could look like this:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Requires more arguments");
return 1;
}

int port = atoi(argv[1]);
char *service = argv[2];
printf("%s", service); //From edit
return 0;
}

You may want to add a check for the value of argc (i.e. argc >= 3), since it will seg fault if there aren't three arguments.

Edit (response to comment):

To print the service, use:

printf("%s", service);

The %s specifies you will print a string of characters (char *) and you simply use service, because you need to specify the pointer.

Edit 2:

If you don't add #include <stdlib.h>, you will receive something along the lines of "warning: implicit declaration of 'atoi' is invalid in C99", which may also produce an error depending on your compiler settings.

Process all arguments except the first one (in a bash script)

Use this:

echo "${@:2}"

The following syntax:

echo "${*:2}"

would work as well, but is not recommended, because as @Gordon already explained, that using *, it runs all of the arguments together as a single argument with spaces, while @ preserves the breaks between them (even if some of the arguments themselves contain spaces). It doesn't make the difference with echo, but it matters for many other commands.



Related Topics



Leave a reply



Submit