I am on MacOS (12.6.1, Monterey) running Emacs 29.1 (installed from https://emacsformacosx.com). I have a set of shell scripts that I have often use with shell-command-on-region (M-|); the scripts are all stored in a ~/bin.

While this worked previously, I now need to enter the full path for this command to work. (I need to enter ~/bin/script.sh rather than just script.sh.)

What is weird is that tab completion for these scripts works in the minibuffer; and if I inspect the variable exec-path, the appropriate directory is there. (If I'm in a shell, I can just use the script name.) If I use the full path for a script (~/bin/script.sh) with shell-command-on-region, that works too. But if I use just the script name I get this error: zsh:1: command not found: script name.sh

So, is there some variable other than exec-path that shell-command-on-region uses that needs to be set? Mac recently switched its default shell from bash to zsh--could that somehow be the cause?

2 Answers 2


When you use a shell-command* function in Emacs, the program that Emacs runs is a shell, rather than the program you've named in the shell command. It's the shell which needs to know how to find and run your command, not Emacs. Emacs only needs to know where the shell is.

Emacs will pass C-hv process-environment to the inferior processes it starts, which includes a PATH, so the shell will inherit that (as well as reading the appropriate shell config files which might also manipulate such things).


Thanks to @phils for the suggestion, which made me realize that shell-command-on-region is somehow not having the PATH variable set for the process. With that hint, and a little more googling, I found another question & answer (linked below) that has a solution; add (setq shell-command-switch "-ic") to my .emacs, so that inferior shell processes spawn as interactive and (if I understand) run the appropriate dot files. This works, though why this is necessary (and why the spawned shell is not inheriting the PATH in the way @phils describes) is not clear.

  • 1
    The shell certainly should be inheriting PATH from process-environment as described. E.g. compare: emacs -Q --batch --eval '(shell-command "echo $PATH")' vs emacs -Q --batch --eval '(setenv "PATH" "foo:bar")' --eval '(shell-command "echo $PATH")'
    – phils
    Sep 28, 2023 at 0:40
  • 1
    Note that you can manipulate process-environment, but it is initialised from the environment Emacs knew when it was started. A common problem I see here on E.S. is the user not starting Emacs from a shell and yet wanting it to know about environment values which are only being set in their shell config files. E.g. setting PATH in ~/.bashrc and expecting Emacs to use that PATH without having started Emacs via bash.
    – phils
    Sep 28, 2023 at 0:45
  • In addition to phils' answer and comments above, you might find this answer useful to help you understand how environments are inherited (in particular, it is quite clear why adding the "-i" switch makes the whole thing work, but if you set up the initial environment of a process properly, it should not be necessary - however, as @db48x says, most people just don't understand how environments are inherited).
    – NickD
    Sep 28, 2023 at 1:19

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.