I have the following command in my .emacs

(setq org-roam-directory
      (concat (getenv "BASEDIR") "/data/org-roam/"))

The purpose is to the set the directory for org-roam (but really it could be any other package) on different systems where the variable $BASEDIR has different paths. $BASEDIR is defined in .bashrc. This works well if I start emacs from the command line, but fails if emacs is started from, e.g., the file manager. Is there a way to have emacs read the shell environment variables at startup, regardless on how it is launched?

EDIT: I am running Ubuntu and Arch with GNOME. The file manager is graphical (nautilus or double commander) but of course this also happens if emacs is launched from the apps menu.

  • Although I understand the temptation to have Emacs read the variables from the file, I think that's the wrong question. The real question is how to arrange it so that every program has access to these variables: that however depends on what OS you are running (in particular is it systemd-based?) and what window system/graphical environment you are running. Can you edit your question and add this information?
    – NickD
    Oct 9, 2021 at 14:10
  • 1
    Your issue isn't reading environment variables (you're doing that correctly), but setting them. You need to understand your shell's initialization order, and how your file manager is invoking Emacs.
    – nega
    Oct 9, 2021 at 16:13
  • More to the point: variables from .bashrc are inherited only by programs started from Bash. If by ‘file manager’ you mean a graphical file manager, then you need to look at how env vars are defined in your graphical environment (Gnome/KDE/whatever). If it's a terminal manager like Midnight Commander, launched from Bash, then the question is why it removes vars from the environment instead of passing them to the editor—you'll need to consult the manager's docs, or set its options. If everything else fails, perhaps the option is indeed to have a specific config file to be read by Emacs.
    – aaa
    Oct 10, 2021 at 9:33
  • And, perhaps the simplest option is—instead of the config variable or file, just have a symlink point at the target directory. This way you actually can use the same path on all the systems and have the symlink resolve it to the actual location.
    – aaa
    Oct 10, 2021 at 9:35

1 Answer 1


aaa is right. You might try setting $BASEDIR in ~/.profile. That file is read when you log in to Gnome, while ~/.bashrc is read when you open up a terminal, basically. (Note that Bash as a login shell doesn't parse ~/.profile if either ~/.bash_profile or ~/.bash_login exists.)

Alternatively you could try is using (shell-command-to-string "$SHELL --login -c 'echo $BASEDIR'") instead of (getenv "BASEDIR"). See How to get the PATH from the SHELL

  • It really depends: e.g. this (the .profile solution) does not work with Wayland. It only works on X11 through an xsession init file which sources `.profile. And the second suffers from the malady that it only potentially fixes Emacs. Neither is a comprehensive solution IMO.
    – NickD
    Oct 10, 2021 at 15:11
  • 1
    @NickD My ~/.profile works in Wayland because I source it in ~/.bash_profile, I had forgot about that. (Might work for the OP too?) Thanks for the heads up. Oct 11, 2021 at 7:06
  • @ArchStanton I am trying the second solution and it almost works. It seems to fail when concat joins the two strings.
    – point618
    Oct 11, 2021 at 10:11
  • This works: (concat (string-trim (shell-command-to-string "$SHELL --login -c 'echo $BASEDIR'")) "/data/org-roam/")) provided that $BASEDIR is in .profile as per comment above.
    – point618
    Oct 11, 2021 at 10:28

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.