sh-mode usually does a great job of auto-magically detecting which shell a file is intended to be run by. It looks at the shebang, for instance. However, I have a bunch of files that are intended to be sourced, not run as executables, and thus I don't have a shebang.

I have my $SHELL environment variable set to bash, but when I open the file, sh-mode still defaults to sh. How do I get it to default to bash?

I've tried running (getenv "SHELL") in both *scratch* and with eval-expression in the shell file's buffer, and they both report "usr/loca/bin/bash". Why doesn't sh-mode respect this? I've been digging through the source code and it really seems like this should be working.

2 Answers 2


As @RichieHH mentioned you can set sh-shell-file via the custom facility or directly for a global default.

Alternatively, and my preferred method, is to set the shell via file-local variables. For example, the first line of your file could look like:

## -*- mode: shell-script; sh-shell: zsh; sh-basic-offset: 3; sh-indentation: 3; coding: utf-8 -*-

This sets the local file to shell-script mode, using the zsh shell, and indentation to 3. (The variable sh-shell is what is set when you call M-x sh-set-shell.) shell-script-mode will then figure out sh-shell-file on its own (presumably based on your path.)

Obviously, you could do something similar with directory local variables.

  • Since I often use vim to make quick edits, ## vim: ts=3:sts=3:sw=3:et:ft=zsh would be a similar modeline.
    – nega
    Feb 12, 2020 at 18:37

Did you look at sh-shell-file? It picks up the shell from that I think reading the docstring.

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.