user1011471 user1011471 - 4 months ago 12
Bash Question

Portable way to build up arguments for a utility in shell?

I'm writing a shell script that's meant to run on a range of machines. Some of these machines have bash 2 or bash 3. Some are running BusyBox 1.18.4 where

bin/bash
exists but


  • /bin/bash --version
    doesn't return anything at all

  • foo=( "hello" "world" )
    complains about a syntax error near the unexpected
    "("
    both with and without the extra spaces just inside the parens ... so arrays seem either limited or missing



There are also more modern or more fully featured Linux and bash versions.

What is the most portable way for a bash script to build up arguments at run time for calling some utility like
find
? I can build up a string but feel that arrays would be a better choice. Except there's that second bullet point above...

Let's say my script is
foo
and you call it like so:
foo -o 1 .jpg .png


Here's some pseudo-code

#!/bin/bash

# handle option -o here
shift $(expr $OPTIND - 1)

# build up parameters for find here
parameters=(my-diretory -type f -maxdepth 2)
if [ -n "$1" ]; then
parameters+=-iname '*$1' -print
shift
fi

while [ $# -gt 0 ]; do
parameters+=-o -iname '*$1' -print
shift
done

find <new positional parameters here> | some-while-loop

Answer

If you need to use mostly-POSIX sh, such as would be available in busybox ash-named-bash, you can build up positional parameters directly with set

$ set -- hello
$ set -- "$@" world
$ printf '%s\n' "$@"
hello
world

For a more apt example:

$ set -- /etc -name '*b*'
$ set -- "$@" -type l -exec readlink {} +
$ find "$@"
/proc/mounts
Comments