Reputation: 11687
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.
Upvotes: 22
Views: 20898
Reputation: 31486
Here is my code, written from scratch, for use with my literate configuration. I cannot use exec-path-from-shell
, because I want to run this code early on, before org-babel-load-file
runs and configures the package management.
(dolist (line (process-lines "bash" "-l" "-c" "export"))
(when (string-match "^.* \\(.*?\\)=\\\"\\(.*\\)\\\"$" line)
(let ((name (match-string 1 line))
(value (match-string 2 line)))
(setenv name value)
(when (string= name "PATH")
(setq exec-path (split-string value path-separator))))))
Upvotes: 0
Reputation: 1
;; 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.
Upvotes: 0
Reputation: 884
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")
Upvotes: 0
Reputation: 19
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'.
Upvotes: 0
Reputation: 15212
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.
Upvotes: 44
Reputation: 3170
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
.
Upvotes: 24
Reputation: 21
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
;;-------------------------------------------------------
Upvotes: 1
Reputation: 1396
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.
Upvotes: 1
Reputation: 1925
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
.
Upvotes: 3
Reputation: 420971
If the $PATH
is set in the terminal you launch emacs from, you can execute system commands through the command M-! <your command> RET
.
Upvotes: 0