# pw (extract Full Name)



## polhallen (May 3, 2013)

Hi folks!

I need to extract the full name of a user and put it inside a variable.

`pw user show guest2`

```
guest2:*:1004:1004::0:0:Pinco Pallino:/home/guest2:/bin/sh
```
Ok, I need to put "Pinco Pallino" into file (or variable) or to output. Is there a command to do this? Or do I need to use sed?

Thanks!

Pol


----------



## kpa (May 3, 2013)

In a bourne compatible shell:

`OIFS=$IFS; IFS=: ; pw user show guest2 | read pw_name pw_passwd pw_uid pw_gid pw_class pw_change pw_expire pw_fullname pw_homedir pw_shell; IFS=$OIFS`

After this the information is in the pw_ variables.


----------



## phoenix (May 3, 2013)

Huh, never would have thought to use *read* like that.  Much simpler than looping with awk(1) to break it down into fields.

Since TMTOWTDI applies (and this is what popped into my head first), the following sticks the name field into a variable called name:

```
name=$( grep "Pinco" /etc/passwd | awk -F: '{ print $8 }' )
```


----------



## kpa (May 4, 2013)

It's called the "let the shell do the work for you" approach :e I only recently discovered that you can use IFS to do all kinds of neat stuff like that.


----------



## wblock@ (May 4, 2013)

Another option:
`pw user show guest2 | cut -d: -f8`


----------



## ta0kira (May 6, 2013)

kpa said:
			
		

> In a bourne compatible shell:
> 
> `OIFS=$IFS; IFS=: ; pw user show guest2 | read pw_name pw_passwd pw_uid pw_gid pw_class pw_change pw_expire pw_fullname pw_homedir pw_shell; IFS=$OIFS`
> 
> After this the information is in the pw_ variables.


This doesn't work at all for me. read is in a subshell here, so the variables aren't available by the time `IFS=$OIFS` happens. In bash, though:
	
	



```
OIFS=$IFS
IFS=:
read pw_name pw_passwd pw_uid pw_gid pw_class pw_change pw_expire pw_fullname pw_homedir pw_shell [B][U]< <(pw user show guest2)[/U][/B]
IFS=$OIFS
```
That keeps read in the same shell. I don't know how to do that in any other shell, though.

Kevin Barry


----------



## kpa (May 7, 2013)

It worked in shells/zsh and I assumed it would be the same for other bourne shells. You're right, the pipe components might get run in subshells depending on their positions in different ways on other shells.

Found this to shed some light on the matter:

http://www.vidarholen.net/contents/blog/?p=178


----------



## Dies_Irae (May 7, 2013)

Why not create one yourself? See getpwnam(3)


```
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>

int main(int argc, char **argv) {
  struct passwd *pwd;

  if(argc != 2) {
    printf("Usage: %s <login>\n",argv[0]);
    exit(0);
  }

  pwd = getpwnam(argv[1]);

  if(pwd != NULL) {
    printf("%s\n",pwd->pw_gecos);
  }
	
  return 0;
}
```


----------



## SirDice (May 7, 2013)

wblock@ said:
			
		

> Another option:
> `pw user show guest2 | cut -d: -f8`



This is slightly more portable:
`getent passwd guest2 | cut -d: -f5`

This should also work on Linux or Solaris, regardless of the backend; LDAP, passwd or otherwise.


----------



## _martin (May 7, 2013)

@@SirDice: Thanks! I was looking for nsquery(1) from HP-UX to have on FreeBSD for some time now. Obviously I didn't look hard enough ;-)

In my opinion OLDIFS= is not needed in oneliners. You are setting "new" IFS only for a subshell these commands are to be run. Once the oneliner is finished, subshell exits. Setting IFS this way doesn't affect your login shell variables.

It does make sense to do this in scripts, especially when you expect IFS to be set to your standard (usually empty).


----------



## kpa (May 8, 2013)

matoatlantis said:
			
		

> In my opinion OLDIFS= is not needed in oneliners. You are setting "new" IFS only for a subshell these commands are to be run. Once the oneliner is finished, subshell exits. Setting IFS this way doesn't affect your login shell variables.
> 
> It does make sense to do this in scripts, especially when you expect IFS to be set to your standard (usually empty).



My solution as I wrote it above is broken slightly and I wasn't aware that different shells run pipeline sections differently in subshells. With ZFS/KSH shells this makes more sense:


```
getent passwd user2 | { OIFS=$IFS; IFS=: ; read pw_name pw_passwd pw_uid pw_gid pw_class pw_change pw_expire pw_fullname pw_homedir pw_shell; IFS=$OIFS }
```


You still have store/restore IFS because the last part of the pipeline is NOT run in a subshell.


----------



## _martin (May 8, 2013)

kpa said:
			
		

> You still have store/restore `IFS` because the last part of the pipeline is NOT run in a subshell.



I don't use zsh; you are right here. You don't need to do this in sh/bash.


----------



## kpa (May 9, 2013)

One more way to do it and this time what OP asked, the full name field only


```
OIFS=$IFS; IFS=:; set -- `getent passwd user2`; echo $5; IFS=$OIFS
```

This should work on shells/bash, shells/mksh, shells/zsh, FreeBSD sh(1) the same way.

Oh and just for the record, the default IFS is not always an empty string 


```
firewall ~ % echo -n $IFS | hd -c
00000000  20 09 0a 00                                       | ...|
0000000      \t  \n  \0                                                
0000004
firewall ~ %
```


----------

