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

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.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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}'

Method 2

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

Method 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]'

Method 4

Maybe this:

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

Method 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.

Method 6

One more way to solve the above problem of finding your default shell, just for fun:

grep ^$USER: /etc/passwd | grep -Eo ':([^:]*)$' | tr -d ':'

Brief description: find the line with the user, find the :/my/shell path at the end, delete the : char from it.


Now, let me expand on @heemayl’s answer, and explain the magical awk code he uses.

1. Just remember the simple stuff:

First off, this:

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

while being 100% correct, and the most “right” answer perhaps, is impossible to remember–you’d have to learn awk and then rewrite it logically from scratch each time. What is easy to remember, however, is this: the default shell for a user is the last field on the user’s line in the “/etc/passwd” file, where fields are separated by the colon : symbol, and each line in that file begins with a username.

Now, with that knowledge, just think: “ok, I need to find my username line in /etc/passwd”. So, do this:

grep $USER /etc/passwd

OR (same effect)

cat /etc/passwd | grep $USER

You’ll get something like this:

my_username:x:1001:1001::/home/my_username:/bin/bash

Cool! My default shell is therefore the last field, which means whatever is after the last : symbol. It is /bin/bash. Done.

2. Explanation of this awk command:

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

awk is a pattern matching language. You can read the GNU awk, or gawk, manual here, which is a great reference: https://www.gnu.org/software/gawk/manual/gawk.html

  1. /etc/passwd at the end is the file to open and process with awk
  2. -F: says to change the “’F’ield separator” from space (the default) to :.
  3. The -v option sets an awk ‘v’ariable you are naming user here, to “foobar”
  4. Now the actual awk program is stored between the single quotes. It’s simply $1 == user {print $NF}. Remember: it is its own programming language! It is based on a pattern match or boolean check { action } type flow. It scans down the file one “record” (or line, by default) at a time. $1 is the first field in any given line, and remember, we told it that fields are separated by :, so the first field is my_username. So, $1 == user says “does the first field equal the value stored in the awk variable user“? If so, do the action specified in curly braces { }. The action is to print the value of $NF, where the internal NF variable contains the ‘N’umber of ‘F’ields for this line. So, the number of fields is 7, since :: contains 1 empty field between those two colons. Therefore, $NF is actually $7, or the value of the 7th field, which is /bin/bash for this user. Behold, the magic of the pattern-matching language, awk.
  5. Done.

3. How to configure a default shell for your user:

What if you want to set or change the default shell for a given user? Use chsh. man chsh says it is used to “change login shell”. Here’s how to use it:

sudo chsh my_username --shell /path/to/my/shell

Ex: set to use the bash shell (my preferred choice) by default:

sudo chsh my_username --shell /bin/bash

Additional awk learning resources:

  1. See some hello world and syntax test files for awk I wrote here: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk
  2. Study git diffn, as an example, here. Note: git diffn is a wrapper I wrote around git diff, to show line numbers.

Method 7

Short and painless:

getent passwd <USER> | cut -d : -f 7

Method 8

Short sed solution:

grep $USER /etc/passwd | sed -r "s/.*/home/$USER:(.*)/1/"

Method 9

Why is everyone making it so complicated? Just cut it from the /etc/passwd file.

grep "^$USER:" /etc/passwd | cut -d: -f7


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x