Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get username from passwd file using shell scripting

From /etc/passwd, I need just the "user" part.

Example:

backup:x:34:34:backup:/var/backups:/bin/sh

has backup as the user.

To extract the user part I am using this now:

perl -pe 's/^(.*?):.*/\1/g' < /etc/passwd

which is a few characters less than my old method:

while read line; do echo ${line%%:*}; done < /etc/passwd

but it sounds like an overkill. It's a lot of text to write.

A Google search gives me:

awk -F  ':' '{print $1}' < /etc/passwd

which is equivalent, I suppose? Is it?

cmp <(perl -pe 's/^(.*?):.*/\1/g' < /etc/passwd) <(awk -F  ':' '{print $1}' < /etc/passwd)

Is there a standard UNIX tool to do this or an easier method using perl? Or cut?

I am a beginner.

BTW, I tried my hand at Python as follows but I suck at it, there may be better ways to do this in Python :(

python -c 'print "\n".join([u[:u.find(":")] for u in open("/etc/passwd")])'

EDIT: actually, maybe more like this for Python:

python -c 'print "\n".join([u.split(":")[0] for u in open("/etc/passwd")])'

Hmm... still very verbose.

like image 828
Robottinosino Avatar asked Jul 28 '26 13:07

Robottinosino


2 Answers

perl -F: -lane 'print $F[0]' < /etc/passwd

does nore-or-less what the awk solution does. -a means split each line of input into fields, -F: means that : is the field delimiter. And the -l outputs a newline for each line of input so you don't have to say print "$F[0]\n".

Since you requested it, the cut solution is even more straightforward:

cut -d: -f1 < /etc/passwd

Meaning: split on :, output the first field.

like image 85
mob Avatar answered Jul 31 '26 04:07

mob


Personally, I would use the awk solution. Cut works, but I often find it not quite flexible enough.

awk -F: '{print $1}' /etc/passwd

Or, more generically, use getent passwd. This will query all the user DB sources configured in /etc/nsswitch.conf, which could be stuff like remote LDAP servers (and also /etc/passwd).

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

If you want a bash-only solution, you could do this. It's weird looking, but it doesn't invoke any external commands. Setting the inter-field separator $IFS tells read what characters to split on. The < /etc/passwd redirection at the end takes effect for the entire loop.

while IFS=: read USER _; do
    echo "$USER"
done < /etc/passwd

(Setting $IFS this way only affects the read command. Generally, you can put variable assignments before any command and they'll only be in effect for that command. For example:

$ FOO=foo
$ echo $FOO
foo
$ FOO=bar true
$ echo $FOO
foo

So no worries about messing up $IFS.)

like image 22
John Kugelman Avatar answered Jul 31 '26 04:07

John Kugelman