1

I have the following simple script:

#!/usr/bin/env bash
ARG_A="test -b"
CMD="./script.sh"

Inside that script, I want to assemble a command ./script.sh -a $ARG_A (i.e ./script.sh -a 'test -b' in this example). Argument for -a might be sourced from a different file, thats why I put it into a separate variable ARG_A.

If I execute the command via

$CMD -a "$ARG_A"

it works as expected. However, I want to put this into CMD so I can get the same result just via

$CMD

I tried different things like

ARG_A=(-a "$ARG_A")
CMD="$CMD ${ARG_A[@]}"

but it doesn't work. Any ideas?

Thanks!

baa2w
  • 314
  • 2
  • 11
  • 2
    BashFAQ #50: http://mywiki.wooledge.org/BashFAQ/050 – Charles Duffy Dec 11 '14 at 00:32
  • ...the FAQ entry being a better resource for this question than the myriad of SO questions it's duplicative of; far too many of the latter have answers suggesting `eval` contrary to best practices. – Charles Duffy Dec 11 '14 at 00:35
  • Thanks Charles for quick the reply, though the answer on top doesn't answer this issue. Also thanks for posting a link to BashFAQ, but it doen't help either. I am just updating an existing script and this is the flow how it goes there, I can't really create a function to run a command. I just thought there is an easy way to append a parameter containing spaces to an existing command as it seems to me quite useful. Thanks though! – baa2w Dec 11 '14 at 00:50
  • I quite disagree that the FAQ doesn't help; section 5 is *directly* on-point. I'd be glad to help one-on-one if you're having trouble finding its applicability, though. – Charles Duffy Dec 11 '14 at 00:53
  • When you're creating `cmd`, what's the use case? Are you trying to generate something eval-safe, or something you can directly execute in your current shell? If you want eval safety, that would be `printf '%q ' "$cmd" "${arg_a[@]}"`, but that _can't_ be executed without `eval`, making it inappropriate for general-purpose use. – Charles Duffy Dec 11 '14 at 00:54
  • If, by contrast, you're trying to just run `$cmd`, which is what it looks like you're saying, then that's literally impossible; you need to run `"${cmd[@]}"` instead to cover all possible corner cases. The FAQ, again, goes into some detail there. – Charles Duffy Dec 11 '14 at 00:55
  • I'm happy to help elucidate the FAQ's relevance -- but stand by it as on-point. (By the way, the use of lower-case names is intentional; upper-case names are reserved by convention for environment variables and builtins -- being in the habit of using lower-case names by default means you don't suddenly wonder what happened when you write `for PATH in "${PATHS[@]}"` and suddenly can't execute any commands). – Charles Duffy Dec 11 '14 at 00:56
  • ...so, to show array-based equivalents to the code given in your question: `arg_a=( test -b ); cmd=( ./script.sh ); cmd=( "${cmd[@]}" "${arg_a[@]}" ); "${cmd[@]}"` – Charles Duffy Dec 11 '14 at 00:59
  • I really appreciate your help Charles! I am not skilled in bash programming (as you probably noticed). As you noted, I tried to just run `$cmd` (which works if neither of the arguments contain spaces, e.g. `cmd="script.sh -a foo -b bar"`, but I tried to make it work even if some of the arguments contain spaces. I trust you its impossible (probably from some good reason). Your last solution is close, thanks. – baa2w Dec 11 '14 at 01:13
  • I assume I can build arguments in the array, e.g. `args=(-a 'test -b'); args=+(-b foo);` etc.. and then run `$cmd "${args[@]}"` assuming `$cmd` contains just the command (e.g. `cmd='./script.sh'`). Its not exactly what I was hoping for, but its acceptable. Thanks again! – baa2w Dec 11 '14 at 01:14
  • If you wanted to just be able to run `cmd` for a shorter/easier calling convention, you could define a function that expands and runs the array: `cmd() { "${cmd[@]}"; }` – Charles Duffy Dec 11 '14 at 01:18
  • ...but, yes; `$cmd` isn't possible in the general case, because even when unquoted, string-splitting takes place without parsing for escape characters and quotes -- so if your command contains arguments with whitespace they can't be held together. Which the FAQ _does_ go into. – Charles Duffy Dec 11 '14 at 01:20

0 Answers0