Is there a way to change the command line arguments in a Bash script? For example, a Bash script is invoked like this:
./foo arg1 arg2
Is there a way to change the value of arg1
within the script? Something like:
$1="chintz"
Is there a way to change the command line arguments in a Bash script? For example, a Bash script is invoked like this:
./foo arg1 arg2
Is there a way to change the value of arg1
within the script? Something like:
$1="chintz"
You have to reset all arguments. To change, e.g., argument $3
:
set -- "${@:1:2}" "new_arg3" "${@:4}"
Basically you set all arguments to their current values, except for the one(s) that you want to change. set --
is also specified by POSIX 7.
The "${@:1:2}"
notation is expanded to the two (hence the 2
in the notation) positional arguments, starting from offset 1
(i.e. $1
). It is a shorthand for "$1" "$2"
in this case, but it is much more useful when you want to replace, e.g., "${17}"
.
eval
at the front of the line per this. –
Ectomorph Optimising for legibility and maintainability, you may be better off assigning $1
and $2
to more meaningful variables (I don't know, input_filename = $1
and output_filename = $2
or something) and then overwriting one of those variables (input_filename = 'chintz'
), leaving the input to the script unchanged, in case it is needed elsewhere.
I found the answer by thkala very helpful, so I have used the idea and expanded on it slightly to enable me to add defaults for any argument which has not been defined. For example:
# Set defaults for the passed arguments (if any) if not defined.
#
arg1=${1:-"default-for-arg-1"}
arg2=${2:-"default-for-arg-2"}
set -- "${arg1}" "${arg2}"
unset arg1 arg2
$1
, $2
, etc. in Bash using set --
As an addition to the main answer on Ask Ubuntu by @Radu Rădeanu here, and to the main answer by @thkala on Stack Overflow here, I'd like to add a really simple example to set multiple arguments at once like this:
# Set arguments `$1`, `$2`, and `$3` to these respective values
set -- "one" "two" "three"
echo "$1 $2 $3"
Output:
one two three
If you have additional arguments after the arguments you want to change, you can keep them by slicing them onto the end, like this:
set -- "one" "two" "three" "${@:4}"
I explain the "${@:4}"
slicing syntax in my answer here: Unix & Linux: Bash: slice of positional parameters. See that answer for much more detail on bash array slicing. Here is a small snippet from it:
# Array slicing basic format 1: grab a certain length starting at a certain # index echo "${@:2:5}" # │ │ # │ └────> slice length # └──────> slice starting index # Array slicing basic format 2: grab all remaining array elements starting at a # certain index through to the end echo "${@:2}" # │ # │ # └──────> slice starting index
So, in the main answer by @thkala, which contains this:
set -- "${@:1:2}" "new_arg3" "${@:4}"
...the explanation is that "${@:1:2}"
grabs the first 2 arguments, "new_arg3"
inserts that as a new argument 3, and "${@:4}"
grabs all arguments from 4 to the end, thereby changing only argument 3 and keeping all other arguments as they were.
For help on the set
built-in bash command, see help set
or look online here: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#The-Set-Builtin
help set
shows the following for the --
argument:
-- Assign any remaining arguments to the positional parameters. If there are no remaining arguments, the positional parameters are unset.
© 2022 - 2024 — McMap. All rights reserved.