49

We can run something like chsh -s /usr/local/bin/zsh to set a new default shell. Is there a command we can run to know what that shell is?

I don’t mean having a terminal open and running a command to know which shell we’re in. I mean like in the example above, if I’m in a terminal with /bin/bash open, what should I run to get /usr/local/bin/zsh if it’s the current default shell?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user137369
  • 5,219
  • 5
  • 31
  • 54

5 Answers5

57

You can use the following command:

echo $SHELL
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bill
  • 5,263
  • 6
  • 35
  • 50
  • 4
    Keep in mind that `SHELL` may not be set by all shells, and there is no guarantee that all shells use the same rules for setting its value. – chepner May 04 '13 at 15:30
  • 3
    @chepner The SHELL variable is something standard. It is not set by the shell itself but before the shell is launched by the login process. – jlliagre May 04 '13 at 20:45
  • 1
    @jilliagre: I was looking in the Shells & Utilities section of the standard, not the Base Definitions. `SHELL` is indeed defined in section 8.3 of the [Environment Variables](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html) chapter of the Base Definitions. – chepner May 04 '13 at 22:41
  • 24
    This doesn't work. SHELL Doesn't show default shell. This information stored in /etc/passwd. Or for Mac use: `dscl . -read /Users/username UserShell` (thanks Lri for the info) – Dmitry Trofimov Nov 27 '13 at 00:36
  • @DmitryTrofimov From man page of `bash` -- `SHELL The full pathname to the shell is kept in this environment variable. If it is not set when the shell starts, bash assigns to it the full pathname of the current user's login shell.` – Bill Nov 27 '13 at 13:18
  • 4
    @Bill Exactly, current login shell is not the same as default shell. Read http://linuxg.net/the-unix-and-linux-shell-variable-shell/ it says that "the $SHELL is the parent shell which spawned the current session". It doesn't equal to default shell just set by chsh – Dmitry Trofimov Nov 27 '13 at 14:44
  • @DmitryTrofimov Sorry, I don't get it. This is what I understand -- if the user doesn't change the value of SHELL, but default its value is the user's login shell, which is default shell. Thus, the current shell may not necessarily be default. – Bill Nov 27 '13 at 14:56
  • 3
    From pubs.opengroup.org: `This variable [SHELL] shall represent a pathname of the user's preferred command language interpreter. ` You cannot expect this variable to have any relationship to the default shell. Users are allowed (perhaps expected!) to set SHELL in their startup files the same way they set EDITOR and PAGER. It may be reasonable to suppose that most users would set SHELL to match their default shell, but when has a user ever behaved reasonably? – William Pursell Apr 14 '18 at 05:46
  • 2
    While `$SHELL` *is* a standard, and it’s useful for some things, I don’t think it’s a suitable answer to this particular question. The *system default shell,* the *user’s* default shell (what this question is asking about), the *current* shell (what many assume `$SHELL` to be), and the “preferred *command language interpreter*” (what `$SHELL` is in reality) are all *very* different. Any script assuming that `$SHELL` is (or ought to be) equivalent to the string that the current user last passed to `chsh` is not going to be portable from user-to-user, let alone system-to-system, except by luck. – Mark G. Jun 28 '18 at 16:28
  • This doesn't work when using makefiles because the makefile will substitute in sh as the shell regardless of what the user's default setting is. – Robert Hafner Dec 20 '21 at 16:28
42

For macOS:

dscl . -read /Users/username UserShell

For the current macOS user:

dscl . -read ~/ UserShell

To parse the path inline using sed:

dscl . -read ~/ UserShell | sed 's/UserShell: //'

Using $SHELL will report the current login shell, not the default login shell. In certain cases, these are not the same. For example, when working in an IDE such as Visual Studio Code which opens an integrated terminal without consulting the default shell.

In addition, as pointed out by Martin C. Martin, $SHELL is a constant that will not change after chsh changes the default login shell.

RWDJ
  • 734
  • 8
  • 13
zmx
  • 611
  • 6
  • 6
  • I am on macOS. Though your code also works, `echo $SHELL` is superior in every way. It’s faster to run, needs less CPU, it’s shorter, and more versatile. – user137369 Jan 09 '17 at 20:34
  • 10
    @user137369 If you call `chsh` from within a shell, it can't update `$SHELL`. So `echo $SHELL` reports the old, now incorrect value, but `dscl . -read /Users/$USER UserShell` reports the new value. – Martin C. Martin Aug 09 '17 at 20:57
  • @user137369, also if you login and then run say `zsh --login`, then $SHELL will not necessarily be the same as your login shell. This answer is correct. – Steven Shaw Oct 09 '19 at 02:31
3

You can grep in the /etc/passwd file for current username, and use cut to extract the appropriate column of information:

grep ^$(id -un): /etc/passwd | cut -d : -f 7-

$(id -un) is a safer than $USER to get user name. Using ^ in front of user name and : after makes sure you don't get a false match if your user name is a sub section of someone else user name.

$SHELL can also be used, as suggested. However it won't work if chsh was used in current shell, as the variable is not updated. Also the variable is not protected against being changed, so it can theoretically be set to something completely different.

Update to attempt an OS X compatible solution. Probably not optimal regexp:

grep ^.*:.*:$(id -u): /etc/passwd | cut -d : -f 7-

This is based on user id's. If the whole user entry is missing, not only user name, then osx must store this somewhere else.

d33tah
  • 10,999
  • 13
  • 68
  • 158
Atle
  • 5,299
  • 1
  • 15
  • 10
  • Which part does't work on OSX? Accessing /etc/passwd to get default shell, or the stuff around to extract user name and desired part of the information? – Atle May 04 '13 at 15:34
  • For some reason, my user account’s name is not present in `/etc/passwd`. – user137369 May 04 '13 at 16:10
  • 15
    [OS X doesn't include normal user accounts in /etc/passwd](http://superuser.com/questions/191330/users-in-etc-passwd-on-mac-os-x). You could also use `dscl . -read /Users/username UserShell`. – Lri May 04 '13 at 16:15
  • Instead of grep and cut (which are really just subsets of awk) you could also just use awk itself if it’s available: `awk -F: '$1==u{print $7}' u=$(id -un) /etc/passwd` Two subprocesses (awk and id) instead of three. :) – Mark G. Jun 28 '18 at 16:08
1

If you want to get the default shell of a user, you could grep file /etc/passwd. like:

grep "$USER" /etc/passwd

# kent:x:1000:1000::/home/kent:/bin/zsh

telling me that the current user (kent) has the default shell /bin/zsh.

If you just want to catch the shell part:

awk -F: -v u="$USER" 'u==$1&&$0=$NF' /etc/passwd

# /bin/zsh

If you want to get the default shell of other user, just replace the $USER part.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kent
  • 189,393
  • 32
  • 233
  • 301
  • 6
    @user137369: OS X doesn't use /etc/password (except during startup), it keeps users in /var/db/dslocal/nodes/Default/users/$USER.plist (which isn't readable except by root). This approach will also fail on other OSes for any user defined in a network domain, or any other non-/etc/password source. BTW, on OS X you could use `dscl /Search -read "/Users/$USER" UserShell | awk '{print $2}'`, but that won't work anywhere else. – Gordon Davisson May 04 '13 at 21:43
  • I am sorry if my answer misleads someone. I don't have any experience with OS X. – Kent May 04 '13 at 21:45
1

In OS X, using the command env | grep -i 'SHELL' produces an output such as: SHELL=/bin/sh (as root, however regular users tend to have /bin/bash as default shell) with a little parsing, the path the shell (and thus the shell itself) could be easily identified and extracted from there..

Crux161
  • 129
  • 2