6

Let's say I want to repeat the same string of environment variables before running various incantations of a command

if [[ some_thing ]]; then
    TZ=GMT LC_ALL=C LONG_ENV_VAR=foo my_command
elif [[ some_other_thing ]]; then
    TZ=GMT LC_ALL=C LONG_ENV_VAR=foo my_command --with-arg
else
    TZ=GMT LC_ALL=C LONG_ENV_VAR=foo my_command --with-other-arg
fi

Is there a way to combine those? Some options

  1. Set them via export

    export TZ=GMT
    export LC_ALL=C
    export LONG_ENV_VAR=foo
    if [[ ]] # ...
    

    This works but I would rather not have them continue to be set in the environment.

  2. Attempt to create a variable variable!

    local cmd_args="TZ=GMT LC_ALL=C LONG_ENV_VAR=foo"
    

    Unfortunately when I tried to run this via:

    $cmd_args my_command
    

    I got TZ=GMT: command not found.

  3. Just list them all out every time.

I also tried Googling for this, but "environment variable variable" isn't the easiest term to search for and I didn't get anywhere. Is there a fix for what I'm trying to do in #2? or am I stuck with some version of #1 and unsetting the vars afterwards?

1
  • Kevin, if any of the existing answers solve your problem, please consider accepting it by using the checkmark next to it. Thank you!
    – Jeff Schaller
    Apr 12, 2017 at 1:33

4 Answers 4

12

I might use a subshell for this:

(
  export TZ=GMT LC_ALL=C LONG_ENV_VAR=foo
  if [[ some_thing ]]; then
    exec my_command
  …
  fi
)

That allows you to clearly set the variables once; have them present for anything you run inside the subshell, and also not be present in the main shell's environment.

12

There are various ways of doing this. Personally, I find functions clearer:

run_this(){
   TZ=GMT LC_ALL=C LONG_ENV_VAR=foo "$@"
}

if [[ some_thing ]]; then
    run_this my_command
elif [[ some_other_thing ]]; then
    run_this my_command --with-arg
else
    run_this my_command --with-other-arg
fi 
6

Point 2. is possible via env:

local env_args="greppable1=foo greppable2=bar"
env $env_args perl -E 'say for grep /greppable/, keys %ENV'

This may be complicated by bash word splitting rules if there's spaces in any of the env args, though.

3
  • 1
    You should clarify that the contents of $env_args have no effect in variable expansion in the command string itself: env A=B echo "$A" echos nothing (or echos what $A already contained).
    – alexis
    Dec 22, 2015 at 22:30
  • @alexis - does A=B echo "$A" behave any differently for you?
    – mikeserv
    Dec 23, 2015 at 8:05
  • It's the same (except that the env command allows pre-expansion of the variable definition string, which was what the OP needs). I should have included the env, but my point applies equally to both versions: any variables in the command itself will be expanded before the custom definitions take effect. The adjusted environment is only useful inside the program. On the other hand, A=B; echo "$A" (as two commands) will of course echo B.
    – alexis
    Dec 23, 2015 at 8:28
0

this is what your arg array is for:

if    thing
then  set --
elif  something
then  set -- --with_arg
else  set -- --other_arg
fi&&  TZ=GMT LC_ALL=C LONG_ENV_VAR=foo my_command "$@"

Remember: an empty "$@" != "". It's just not there.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .