I have a problem passing parameters if the parameters may contain wildcards and/or spaces, if those parameters are optional. Since this sounds pretty abstract, let's have a small example: The following shell script some_command.sh expects 2 or 3 arguments. The first argument is supposed to be a command line switch, the second argument is optional and, if present, must be a command line switch of the form --NAME=VALUE, and the final argument is required and can be anything:#!/bin/bash# This is file some_command.sh# Synopsis:# some_command.sh --switch1=val1 [--switch2=val2] argecho switch1: $1shiftif [[ $1 == --*=* ]]then  echo switch2 ($1) detected  shiftfiecho argument is ${1:?argument missing}Let's assume that I am calling some_command.sh from some other script, caller.sh, in the following way:#!/bin/bash# This is file caller.shif [[ ${1:-x} == x ]]then  switch=--abc=long argumentelse  switch=fisome_command.sh --exclude=*~ $switch argNote the quoting. The quotes around --exclude are necessary, because the wildcard expression must not be expanded by the shell, and the quotes around $switch are necessary, because $switch may contain text having spaces, and the argument must not be broken up on the spaces.The intention is that if we execute caller.sh x, this should result intosome_command.sh --exclude=*~ --abc=long argument  argand if we execute, say, caller.sh y, this should turn intosome_command.sh --exclude=*~ argThe caller.sh which I have provided here, does not work correctly, because in the latter case, it would executesome_command.sh --exclude*~  argwhich is incorrect.I tried to prefix the command with eval. While this would solve the problem with $switch, it would also remove the quotes around --exclude, and the wildcards would be evaluated by the shell.I guess I could go on with the eval, and just use an extra level of quoting, i.e. \--exclude*~\, but this is an awful solution. I wonder if somebody has a cleaner way to do it.In case you wonder why I came to this question: I stumbled over the problem when writing scripts invoking zip, and since these scripts should be able to cope with spaces in file names.BTW, the problem, as stated, occurs with bash and zsh. I am also interested in clever solutions, which work only with one of those shells.
Problem with passing parameters containing spaces and wild card characters
bash;shell script;zsh;quoting
Use an array since that can expand to a variable number of arguments:#!/bin/bash# This is file caller.bashswitch=()if [[ ${1-x} == x ]]then  switch=(--abc=long argument)fisome_command.sh --exclude=*~ ${switch[@]} argOr you could use the ${var+...} syntax:#!/bin/sh# This is file caller.shunset switchif [ ${1-x} = x ]then  switch=--abc=long argumentfisome_command.sh --exclude=*~ ${switch+$switch} argNote that with zsh, you can do:#!/bin/zshswitch=if [ ${1-x} = x ]then  switch=--abc=long argumentfisome_command.sh --exclude=*~ $switch argzsh doesn't do split+glob upon parameter expansion, but it does empty removal which is what you want here.