I need to use my $PATH
in Emacs to run some commands. How can I make Emacs use it? I installed Emacs from Ubuntu repositories.
-
http://stackoverflow.com/questions/1393400/commands-from-bashrc-not-available-in-emacs – Vivek Goel Jun 20 '11 at 12:32
-
[This answer](https://emacs.stackexchange.com/a/29120/8849) seems to be a perfect resolution. – Yantao Xie Sep 13 '17 at 01:21
-
[The DotFiles article](http://mywiki.wooledge.org/DotFiles) covers specifics of bash dot-files load and provides background context for better understanding of the processes discussed in this QA thread. – Y. E. Aug 03 '21 at 10:35
9 Answers
Here's a trick I use to ensure my GUI Emacs always sees the same $PATH
that I get inside a shell:
(defun set-exec-path-from-shell-PATH ()
(let ((path-from-shell (replace-regexp-in-string
"[ \t\n]*$"
""
(shell-command-to-string "$SHELL --login -i -c 'echo $PATH'"))))
(setenv "PATH" path-from-shell)
(setq eshell-path-env path-from-shell) ; for eshell users
(setq exec-path (split-string path-from-shell path-separator))))
(when window-system (set-exec-path-from-shell-PATH))
Specifically, on OS X, a graphical Emacs will not pick up the user's shell's definition of $PATH
, so this trick helps me on that platform.
Update: this code has now been published as an elisp library called exec-path-from-shell and installable packages are available in MELPA.

- 15,002
- 2
- 49
- 43
-
This fixes the same problem in ubuntu 13.04 (I used the package manager install) – Anake Sep 23 '13 at 11:11
-
1It does not seem to use aliases. Would not expect it from because of the name though. Is there something for also getting the aliases of normal bash? – Zelphir Kaltstahl Feb 27 '17 at 19:57
-
Emacs will never use your bash aliases, sorry: those are only available inside bash sessions. This code and the exec-path-from-shell package simply allow Emacs to reliably locate the same executable files and scripts that are visible in your bash sessions. – sanityinc Mar 01 '17 at 07:30
-
-
@Welgriv No, functions work like bash aliases, so my comment above applies to them too. – sanityinc Jun 16 '20 at 21:03
-
See [answer by Hugues](https://stackoverflow.com/a/42036157/1319821) that also covers aliases. – Y. E. Aug 03 '21 at 10:17
A more general solution (to set all variables and aliases, not just PATH
) is given in https://stackoverflow.com/a/12229404/1190077 -- the key is to set:
(setq shell-command-switch "-ic")
which overrides the default "-c"
(execute the following command). The addition of "-i"
forces the bash shell into interactive mode, which leads to the sourcing of ~/.bashrc
.
-
1Seems to work better than the accepted answer since it allow bash functions using. – Welgriv Jun 15 '20 at 08:48
-
On MacOS, with this setup, I kept everything I had at `~/.bash_profile`, then added line `source ~/.bash_profile` to `~/.bashrc`. As simple as is. Finally my `$PATH` and conveniency aliases available smoothly at `Emacs`'s `M-x shell-command`. – Y. E. Aug 03 '21 at 10:30
If your env vars aren't picked up it may be due to the way emacs is started. Check the menuitem or whatever and try changing emacs
to bash -c emacs
.

- 1,897
- 2
- 16
- 29
I came up with something similar for sourcing my .bash_profile. If you only care about PATH, one of the other answers above is simpler.
It works by executing source ~/.bash_profile ; echo post-env; env
then throwing away everything before "post-env", and then parsing out the values in the "key=value" format that the "env" command prints.
It probably doesn't handle every case perfectly, but works well enough for me.
;;-------------------------------------------------------
;; begin sourcing of .bash_profile
;; only do this on Mac OS X
(when (string= system-type "darwin")
;; require common lisp extensions, for search
(require 'cl)
(defun src-shell-unescape (string)
;; replace \n \t \r \b \a \v \\
;; and octal escapes of the form \0nn
(replace-regexp-in-string
"\\\\\\([ntrbav]\\|\\(\\\\\\)\\|\\(0[0-7][0-7]\\)\\)"
(lambda (str)
;; interpret octal expressions
;; of the form "\0nn"
(let ((char1 (aref str 1)))
(cond ((= ?0 (aref str 1))
(byte-to-string
(+ (* (- (aref str 2) ?0) 8)
(- (aref str 3) ?0))))
((eq char1 ?n) "\n")
((eq char1 ?t) "\t")
((eq char1 ?r) "\r")
((eq char1 ?b) "\b")
((eq char1 ?a) "\a")
((eq char1 ?v) "\v")
((eq char1 ?\\) "\\\\")
(t "")))) string))
(defun src-set-environment-from-env-output(env-output)
;; set the environment from shell's "env" output
(let ((lines (split-string env-output "\n" t)))
(dolist (line lines)
(let ((idx-equals (search "=" line)))
(when (and (not (eq idx-equals nil))
(> idx-equals 1))
(let ((key (substring line 0 idx-equals))
(value (substring line (+ idx-equals 1))))
(setenv key (src-shell-unescape value))
;; (message "%s = %s" key value)
))))))
(defun src-source-shell-file (file-name)
;; if your shell is sh rather than bash, the "source " may need
;; to be ". " instead
(let* ((command (concat "source '" file-name "'; echo 'post-env'; env"))
(output (shell-command-to-string command))
(idx-post-env (search "post-env" output)))
(if (eq nil idx-post-env)
(message "Didn't find expected output after sourcing %s. Found: %s" file-name output)
(let ((trimmed-output (substring output idx-post-env)))
;; (message "trimmed-output: %s" trimmed-output)
(src-set-environment-from-env-output trimmed-output)))))
(src-source-shell-file (expand-file-name "~/.bash_profile")))
;; end sourcing of .bash_profile
;;-------------------------------------------------------

- 21
- 2
You can add path settings to /etc/profile.d such as
# /etc/profile.d/path.sh
export PATH="$PATH:/usr/local"
In Ubuntu, I remember all sessions source your ~/.xsessionrc
, so you also can set path in this file for GUI apps.

- 1,091
- 8
- 20
There are many Emacs packages that update $PATH environment variable and the 'exec-path'. That's because Emacs don't assume definitions in BASH related files, such as '~/.bashrc'.
All definitions you need to have in any program not executed from a terminal shell, must be moved to '~/.profile', these are loaded in the system startup.
Some old systems need to manually load user profile from '/etc/profile'.

- 19
- 3
If the $PATH
is set in the terminal you launch emacs from, you can execute system commands through the command M-! <your command> RET
.

- 413,195
- 112
- 811
- 826
This should really be a comment but the formatting didn't work out. The answer from @Hueges worked for me except it caused issues with dired
mode. Someone with stronger elisp could do better than this, but it worked for me.
;; temporarily set shell-command-switch to -ic until function completes
(defun wrap-shell-command (func &rest args)
(let ((current-shell-command-switch shell-command-switch))
(setq shell-command-switch "-ic")
(apply func args)
(setq shell-command-switch current-shell-command-switch)))
;; usage
(wrap-shell-command 'shell-command "func-define-in-bashrc" "other" "args")

- 876
- 4
- 8
;; set shell-command-switch to -ic only for async-shell-command
(defun pre-command-hook-fn ()
"."
(if (string= current-minibuffer-command "async-shell-command")
(setq shell-command-switch "-ic")
(setq shell-command-switch "-c")
)
)
(add-hook 'minibuffer-setup-hook 'pre-command-hook-fn)
TODO: Modify 'exec-path' to make minibuffer completion use interactive shell's PATH.

- 1
- 2