I want to run a command that sources a script to take on some env. variables before executing, without sourcing them in my current shell.


export test=1

None of these commands echo the env. variable:

a) Shouldn't this work? Aren't I just executing these commands in a new shell and returning the output?

$ bash -c "source test.env && echo $test"

b) Here I execute test.env and try to run echo $test in the same process using exec.

$ bash -c "./test.env && exec echo $test"

c) Lastly I just tried this since it was a possible permutation. But it executes test.env and the echo command as separate processes.

$ bash -c "./test.env && echo $test"

And how can I get this to work where the env. variables are sourced before the 2nd command is executed?


You must escape dollar sign $ in your first command, otherwise bash will expand it before your command executed:

$ bash -c "source test.env && echo \$test"

Or you should use single quote instead of double quote:

$ bash -c 'source test.env && echo $test'
  • it's the simplest errors that are the most stumping
    – Salami
    Jun 8 '14 at 18:09

If the goal is only to handle setting ENV before running a process and avoiding affecting the current shell then execing the bash executable might not be the most efficient way to go about it.

( . /dev/fd/4 && echo "$i" ) 4<<\SCRIPT
    i='i is set here in the subshell'

echo ${i?but i isnt set here because it was set in the subshell}


i is set here in the subshell
sh: line 5: i: but i isnt set here because it was set in the subshell

You can of course substitute the link to the heredoc's file-descriptor with a regular file - I just used it to demonstrate it.

But if you do exec an outside process - such as bash or any other - rather than a shell builtin then you don't need the subshell.

one=1 two=2 \
    bash -c 'echo "${cmd=This is command #}$one" 
             echo "${cmd}$two"'
echo "${one?this var was only set for the execed ENV}"


This is command #1
This is command #2
sh: line 2: one: this var was only set for the execed ENV

And if that outside process is bash or any other shell conforming to the POSIX standard of accepting -stdin as default, you can just write your script directly to a |pipe file...

{ echo PS1=
  echo 'echo "$PS1"'
  cat /etc/skel/.bashrc
  echo 'echo "$PS1"'
} | bash
echo "${PS1:?unset here again}"


#blank line from first echo
[\u@\h \W]\$
sh: line 7: PS1: unset here again

As written, the shell is expanding $test before it is passed to your command. You can stop this from happening by using a ' instead of ".

bash -c 'source test.env && echo $test'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.