I have an org-mode file that contains a BASH script in an org-babel source block. I would like to pass environmental variable values to it through :var.

something like:

#+begin_src sh :var VAR1="~/foo"
  mkdir ${VAR1}/test


#+begin_src sh :var VAR1="${MY_ENV_VAR}/foo"
  mkdir ${VAR1}/test

When I run the blocks with C-c C-c, they complain about not being able to find the ${VAR1} directory.

I think ${VAR1} is not being expanded properly inside the bash shell.

What's the right way to do it?

  • Try #+begin_src sh :var VAR1=(substitute-in-file-name "$MY_ENV_VAR/foo").
    – Tobias
    Jun 22, 2015 at 8:06
  • @Tobias Thanks for your reply. I tried you solution. It works environment variable, such as, ${HOME}, but still doesn't work with ~.
    – Enze Chi
    Jun 23, 2015 at 12:09
  • 2
    Try #+begin_src sh :var VAR1=(expand-file-name (substitute-in-file-name "$MY_ENV_VAR/foo")). This is ugly, I have to admit.
    – Tobias
    Jun 23, 2015 at 12:16

1 Answer 1


First Thanks @Tobias for the answer which solved my problem. But after more test, I just found that still has small issue about the solution if use expand-file-name.

For example, if your environment variable is just string instead of real file name or directory (like ${USER}), the expand-file-name would add some directory before that and that may not what your want. So you have to know what's the variable would look like before you code it.

To solve this problem, I just write a simple function which only apply expand-file-name if the result of subsitute-in-file-name start with ~.


(defun ec-expand-env (str)
  "Expand the environment variables in the STR."
  (let ((expanded-str (substitute-in-file-name str)))
    (if (string-prefix-p "~" expanded-str)
        (expand-file-name expanded-str)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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