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

0
1
Asked By MellowCedar42 On

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?

3 Answers

Answered By QuartzMango7 On

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.

Answered By BrightPine83 On

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.

Answered By NimbleOrbit5 On

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.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.