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?

3 Answers 3


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, 2014 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'

You must log in to answer this question.

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