1

I am trying to read in two fields from the /etc/passwd file (1,6) into an array.
I can get the fields into a variable but not into an array.

This code will get all users over 1000 and return the user and home directory.

users=$(awk -F'[:]' '{if ($3 >= 1000 && $3 != 65534) print $1}' /etc/passwd)
hemalp108
  • 1,209
  • 1
  • 15
  • 23
  • 2
    This code only returns the user, not the home directory. Further, what would your array look like if you were to define it manually for, say, 2 users? – chepner Oct 21 '16 at 13:53

2 Answers2

1

Try this:

while IFS=: read -r user _ uid _ _ homedir _
do
    (( uid > 999 && uid != 65534 )) && arr+=( "$user":"$homedir" )
done < "/etc/passwd"

printf '%s\n' "${arr[@]}"

This script process /etc/password reading each line in a while loop.

  • Each line is split on the value of $IFS.
  • The $IFS is set to : only for the duration of the read command.
  • The values split are assigned to several variables (user, uid, homedir, _).
  • The variable _ is used to discard values that are not needed.
  • Then, only if the uid is valid, a record is added to the array (the +=(…)).
  • The records in the array are joined with a colon (:)
0

To offer an awk alternative to soronta's helpful and well-explained answer:

IFS=$'\n' read -d '' -ra usersAndHomeDirs < \
  <(awk -F':' '$3 >= 10 && $3 != 65534 { print $1, $6 }' /etc/passwd)
  • -d '' tells read to read the entire input as a whole,
  • IFS=$'\n' tells read to split the input into lines, and store them in elements of array (-a) usersAndHomeDir (-r turns off \ interpretation in the input, and in most cases should be added by default).
  • < <(awk ..) then uses a process substitution (<(...)) to make awk output "<user> <home-dir>" lines, and feeds them to read via stdin (<).

Note that each element of "${usersAndHomeDirs[@]}" is now a single "<user> <home-dir>" string, which you'll have to split into its components later.
(Bash doesn't offer a way to fill two arrays in parallel.)

To use something other than a space as the separator, pass -v OFS=<separator-string> to the awk command.

Letting awk process the input file will be much faster in general than doing it in a shell loop, though in this particular case it may not make much of a difference, if your /etc/passwd file is smallish.

Community
  • 1
  • 1
mklement0
  • 382,024
  • 64
  • 607
  • 775