What’s the cleanest way to add an optional argument in Bash?

August 4, 2026 3 answers
Asked by MellowCedar42
I have a Bash function that calls `notify-send` with a fixed set of options, plus an optional `--icon="$file"` argument when `$target` is not `pixel`. Right now I build an array first so I can invoke `notify-send` only once: ```bash notify() { local -a args if [[ "$target" != pixel ]]; then args=(--icon="$file" "$@") else args=("$@") fi notify-send --hint=string:x-dunst-stack-tag:shot --hint=string:synchronous:shot --app-name=screenshot "${args[@]}" } ``` The `args=("$@")` branch feels a little unnecessary, but duplicating the command just to conditionally add one argument also seems repetitive. Is there a cleaner and still safe way to handle this?

Answers

NimbleOrbit5
You can also append conditionally to an array, then append the original arguments: ```bash notify() { local -a args [[ $target != pixel ]] && args+=(--icon="$file") args+=("$@") notify-send --hint=string:x-dunst-stack-tag:shot --hint=string:synchronous:shot --app-name=screenshot "${args[@]}" } ``` This keeps everything as separate array elements, so filenames or other arguments containing spaces remain safe. It also avoids duplicating the `notify-send` invocation.
Reply to this answer
BrightPine83
A parameter expansion can be used for an optional argument, but it is easy to get quoting wrong. An unquoted expansion may split words or perform pathname expansion, while a quoted expansion can leave an empty argument behind. For command arguments, an array is generally clearer and safer than trying to construct a shell fragment with expansion or `eval`.

VelvetRook26: Exactly—`eval` should not be needed here. Building an array and expanding it with `"${args[@]}"` is the robust approach.

Reply to this answer
QuartzMango7
The array assignment is perfectly fine, but you can avoid the temporary array by conditionally prepending to the function’s positional parameters: ```bash notify() { if [[ $target != pixel ]]; then set -- --icon="$file" "$@" fi notify-send --hint=string:x-dunst-stack-tag:shot --hint=string:synchronous:shot --app-name=screenshot "$@" } ``` Because this happens inside the function, `set --` only changes that function’s positional parameters. Quoting the arguments preserves spaces and prevents them from being interpreted as shell syntax.

CrispLake19: This is shorter, although I prefer keeping the explicit array when I want the argument construction and error handling to be especially obvious. The practical difference here is negligible.

Reply to this answer

Add your answer

Answers are reviewed before publication.

Related Discussions