Finding out the default shell of a user within a shell script

43,893

Solution 1

$ finger $USER|grep -oP 'Shell: \K.*'
/bin/mksh

Solution 2

The environment variable, SHELL would always expands to the default login shell of the invoking user (gets the value from /etc/passwd).

For any other given user, you need to do some processing with /etc/passwd, here is a simple awk snippet:

awk -F: -v user="foobar" '$1 == user {print $NF}' /etc/passwd

Replace foobar with the actual username.

If you have ldap (or something similar in place), use getent to get the database instead of directly parsing /etc/passwd:

getent passwd | awk -F: -v user="foobar" '$1 == user {print $NF}'

or cleanest approach, let getent do the parsing (thanks to @Kusalananda):

getent passwd foobar | awk -F: '{print $NF}'

Solution 3

Since getent isn't a standard command on MacOS, you may wish to use a lower level getpwuid call that will consult the naming services the machine is configured for. This may require calling out to perl or python, which are pretty common across most Unix-like platforms

eg this will return the shell for the current user:

perl -e '@x=getpwuid($<); print $x[8]'

Solution 4

Maybe this:

grep ^$USER: /etc/passwd | cut -f 7 -d :

Solution 5

You can get the user's default shell from the environment like this:

echo $SHELL

But not like this:

echo $0

The latter will just tell you what shell your script is currently using. So you want the first option above.

Share:
43,893

Related videos on Youtube

Spaniard89
Author by

Spaniard89

Updated on September 18, 2022

Comments

  • Spaniard89
    Spaniard89 almost 2 years

    I was wondering if there's a way to find out the default shell of the current user within a shell script?

    Use case: I am working on a script that sets an alias for a command and this alias is set within a shell script.

    !# /bin/bash
    alias = 'some command to set the alias'
    

    There's a logic in the script where it tries to find the default shell of the user that executes the script and adds this alias in the respective ~/.bashrc or ~/.zshrc file

    But as I am adding a shebang in the front of the script and explicitly asking it to use bash, answers posted here always return bash as expected although I am executing this script on a ZSH terminal.

    Is there a way to get the shell type where the script is executed regardless of the shebang set?

    I am looking for a solution that works on both Mac and all the linux based bistro.

    • Spaniard89
      Spaniard89 over 7 years
      @StephenRauch I should have mentioned it earlier, I am looking for a method that works on both Mac and Linux based system. /etc/passwd on Mac does not contain the user information and its only consulted in a single user mode.
    • terdon
      terdon over 7 years
      What does /etc/passwd have on OSX? I had a quick look online and it appears that the shell is there, just not the username. The user ID's still there though, why don't you use that?
    • jamesqf
      jamesqf over 7 years
      I'd wonder if it's even possible to have an exhaustive list of shells. Or do all shell startup files always conform to .{name_of_shell}rc?
    • Sergey Ponomarev
      Sergey Ponomarev over 3 years
      Here is an answer to OSX stackoverflow.com/a/16375660/1049542
  • Spaniard89
    Spaniard89 over 7 years
    Thanks for the answer. I should have mentioned it earlier, I am looking for a method that works on both Mac and Linux based system. /etc/passwd on Mac does not contain the user information and its only consulted in a single user mode.
  • Spaniard89
    Spaniard89 over 7 years
    Thanks it works like a charm! This is the only solution that probably works for both mac and linux based bistro.
  • Spaniard89
    Spaniard89 over 7 years
    BTW, I edited the command a little bit to make it agnostic to all OS finger $USER | grep 'Shell:*' | cut -f3 -d ":" as the grep options -P is not supported on Mac.
  • Stephen Harris
    Stephen Harris over 7 years
    Note that finger may not be installed on all machines. It's an optional package on RedHat based systems.
  • Ipor Sircer
    Ipor Sircer over 7 years
    @Kishorepandey: you can use getent|grep ^$USER:|cut -f: -f7 instead of finger, if finger was not installed by default.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 7 years
    @Kishorepandey Don't do this. Use the SHELL environment variable if it's present. Looking at the user database will give you a result (the user's login shell) but it might not be the right result (the user's favorite interactive shell) — it depends on the user's configuration.
  • Kusalananda
    Kusalananda about 7 years
    This does not improve on any of the already given answers.
  • smac89
    smac89 almost 6 years
    finger $USER | pcregrep --color -io1 'shell:\s*(.+)'
  • Gabriel Staples
    Gabriel Staples about 4 years
    For an explanation of that awk command, see here: unix.stackexchange.com/a/589221/114401
  • Rich
    Rich almost 4 years
    Use getent unless you're never ever going to use a directory for authentication ever. If Unix doesn't have getent you need to restate your question to find the equivalent in your particular Unix distro.
  • Rich
    Rich almost 4 years
    $SHELL is not guaranteed to be the user's default shell either. You want getent or its macOS equivalent.
  • Konrad Rudolph
    Konrad Rudolph over 2 years
    Alas the SHELL environment variable doesn’t always exist! In fact, even when the parameter exists in a shell, it might not be exported. And using getent (or finger) works well on Linux but fails on some other systems. I’m not aware of a foolproof, maximally portable way. As a fallback I’d just iterate a few common shell path locations and, if those don’t exist, call it a day.
  • Konrad Rudolph
    Konrad Rudolph over 2 years
    In general you should not inspect /etc/passwd manually, it isn’t guaranteed to be synchronised with the user database if directory services (e.g. LDAP) are used. Whereas getent will continue to work (if it is installed).
  • Stéphane Chazelas
    Stéphane Chazelas over 2 years
    That only works on systems where the user db is stored in /etc/passwd, as opposed to LDAP, NIS+, SQL... That also could give you the wrong result if $USER contains regex operators (such as . which is common in usernames). There's no guarantee $USER will contain the current user name. $LOGNAME (from processes that are part of a login session) is standard, so are $(logname), $(id -un) (though the latter only gives one user with the current process uid as uid, which may not be the same user as the one who logged in in cases where several users share the same uid)
  • Admin
    Admin about 2 years
    Responding to Gilles's comment: $SHELL is the user's login shell. My login shell is fish: if I unset the SHELL variable and then launch bash, SHELL is "/path/to/fish"