简体   繁体   中英

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.

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.

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

Perl provides a built-in to do this for you: getpwent

endpwent(); # reset to beginning of file in case some other code has read some entries already
while ( my ($username) = getpwent() ) { 
    print "user: $username\n";
}
endpwent();

getpwuid and getpwnam can be used to look up a particular name or id; all three get functions return a list of all the standard fields on a line.

If all you need is the user name, the `id' command will suffice and is much simpler.

USER=`id -un`

For other parts of the password file entry, I would still use one of the above options.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM