No, don't squash multiple filenames into a single string. For one, because the shells don't support that(*), but also because in general, file names can be any strings. There's no character or character sequence you could use as a separator that wouldn't be valid in a filename. Except for the NUL byte, but you can't pass that as a command line argument anyway.
(* With the possible exception of zsh.)
So, just fill two arrays with the filenames you get as arguments. From there, it's also simple to loop over the lists.
Though, getopts will stop when it sees a non-option argument, so we'll have to look manually for some separator string. (Which again, necessarily is something that could be a filename, but at least it'll need to match a complete filename for things to get messed up. Let's pick ::, and if you ever have a filename like that, be sure to pass it as ./::.)
#!/bin/bash while getopts "xy" option; do # silly placeholder echo "option $option" done shift $(( OPTIND - 1 )) list=a lista=() listb=() while [ "$1" ]; do case $1 in ::) list=b;; *) if [ "$list" = a ]; then lista+=("$1") else listb+=("$1") fi;; esac shift done printf "files in list a:\n" printf " <%s>\n" "${lista[@]}" printf "\n" printf "files in list b:\n" printf " <%s>\n" "${listb[@]}" printf "\n" printf "combinations:\n" for b in "${listb[@]}"; do for a in "${lista[@]}"; do printf "<%s> <%s>\n" "$a" "$b" done done
running that gives something like this:
$ bash lists.sh -x a* :: b* option x files in list a: <a1.txt> <a2.txt> <a3.txt> files in list b: <b1.txt> <b2.txt> combinations: <a1.txt> <b1.txt> <a2.txt> <b1.txt> <a3.txt> <b1.txt> <a1.txt> <b2.txt> <a2.txt> <b2.txt> <a3.txt> <b2.txt>
Adjust the getopts loop as necessary, but remember to keep the shift command to clear the options getopts already processed.
That is, I assumed above you wanted to combine first A with all Bs, and second A with all Bs, etc.
If, instead, you want first A with first B, second A with second B, etc., then that last loop would need to be something like:
i=0 # stop when either list ends while [ "${lista[i]}" ] && [ "${listb[i]}" ]; do printf "<%s> <%s>\n" "${lista[i]}" "${listb[i]}" i=$((i + 1)) done
Though, as @terdon noted in a comment, GNU parallel could do this directly.
Like so:
$ parallel echo {1} {2} ::: a*.txt ::: b*.txt a1.txt b1.txt a1.txt b2.txt a2.txt b1.txt a2.txt b2.txt a3.txt b1.txt a3.txt b2.txt # or $ parallel echo {1} {2} ::: a*.txt :::+ b*.txt a1.txt b1.txt a2.txt b2.txt
It passes the given command through a shell, se special characters would need some extra quoting. And of course you need to be careful with the separators, with that extra + being rather meaningful.
multitool.sh -a a*.txt -b b*.txt, the shell will normally expanda*.txtto the list of the matching files. So for your script it looks like you ranmultitool.sh -a a1.txt a2.txt -b b1.txt b2.txtIs this what you want? Or do you want to get the literala*.txtin your script? Then you would need to quote the patterns in the command line.parallelcan do this, so can a combination ofpasteandxargs. I would urge you to ask a new question with the details of what you need to do because I really doubt rolling your own script will be the best solution here.