Ask Ubuntu is a question and answer site for Ubuntu users and developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I need somebody who could help an exercise. I can only use shell scripting and awk to do it:

You have a text file called users.txt with this info inside:


Peter:7777:/home/store ;

Quinn:7777:/home/accounts ;

David:7777:/home/secondstore ;

Daniel:7777:/home/address ;

The script should create an user using the first word of each line, the second word of each line will be used as password, and the third one as the home directory.

I would be very grateful If anybody can point me in the right direction

share|improve this question
Google and do your homework. :) – Nehal J. Wani May 15 '14 at 16:33

awk -F: '{print $1}' users.txt will give you access to the username field
awk -F: '{print $2}' users.txt --> password field
awk -F: '{print $3}' users.txt --> home directory field

you could do something like:

user=`awk -F: '{print $1}' users.txt`;
path=`awk -F: '{print $3}' users.txt`;
useradd -d $path -m $user;
share|improve this answer
The third awk is incorrect. It'll include the ` ;` from the end of the lines. – Oli May 16 '14 at 20:29
If I can use sed I could do path=awk -F: '{print $3}' users.txt | sed 's/;$//'; – user257256 May 16 '14 at 22:13
I can use sed, but the problem in this case is the ammount of data it saves... How can I put a vector inside an awk file? – marcos ruiz May 18 '14 at 16:31

The both commands in the while loop need to be run as root, so either add sudos or save this as a bash script and run that with sudo (probably preferable).

awk -F ':| ' '{print $1, $2, $3}' users.txt |
while read user password homedir; do
    adduser --home "$homedir" "$user"
    echo "$password" | passwd "$user" --stdin

Alternatively, as you've pointed out, you can do more inside awk. We can have it print the entire command:

$ awk -F ':| ' '{ print("adduser --home", $3, $1"; echo", $2 " | passwd", $1) }' users.txt
adduser --home /home/almacen1 Jperez; echo 1234 | passwd Jperez
adduser --home /home/contabilidad1 Lgomez; echo 1234 | passwd Lgomez
adduser --home /home/almacen2 Pfernandez; echo 1234 | passwd Pfernandez
adduser --home /home/direccion1 Mramos; echo 1234 | passwd Mramos

And then just have it pipe all that into a shell (while running):

$ awk -F ':| ' '{ print("adduser --home", $3, $1"; echo", $2 " | passwd", $1) | "/bin/bash" }' users.txt
adduser: Only root may add a user or group to the system.
passwd: user 'Jperez' does not exist
adduser: Only root may add a user or group to the system.
passwd: user 'Lgomez' does not exist
adduser: Only root may add a user or group to the system.
passwd: user 'Pfernandez' does not exist
adduser: Only root may add a user or group to the system.
passwd: user 'Mramos' does not exist

Obviously you would need to run the above with sudo (or as root) in order for it to run (that's why it's vomiting errors). You could use awk's system() command but then you have to spend more time concatenating the strings. print() makes this really simple so I went with that.

Just for clarification, by that I mean to run sudo awk -F ':| ' '{ print("adduser --home", $3, $1"; echo", $2 " | passwd", $1) | "/bin/bash" }' users.txt

share|improve this answer
Don't need awk here: while IFS=: read user password homedir; do ... done < users.txt -- will have to trim trailing stuff from the line though. – glenn jackman May 15 '14 at 21:08
@glennjackman sure, just the question asks for it explicitly. – Oli May 15 '14 at 21:48
the problem here is how the program knows that users are in the first field, the passwords are the second field of each line etc...?...thanks for your help – marcos ruiz May 18 '14 at 17:03
@marcosruiz I don't follow. awk processes the line logically And you've told us the order of the lines. That's how. – Oli May 18 '14 at 17:33
sorry, I'm pretty newbie at shellscripting...what do you mean by "logicaly"? one after anoter in a sequence? .... is there any way of doing this exercise with AWK and the SYSTEM command inside AWK? because that's the hint our teacher gave us(but he pointed there were other ways of doing the exercise without AWK)... thanks for your time and help – marcos ruiz May 20 '14 at 8:46

Set the internal field separator to : and then simply ignore the last character of ; by any method... using substring or chomping it off.

This code should point you in the right direction.

This is a random example of IFS var in use

vals='/mnt,/var/lib/vmware/Virtual Machines,/dev,/proc,/sys,/tmp,/usr/portage,/var/tmp'
for i in $vals; do echo $i; done
unset IFS

In your case you'd set IFS=: and run that type of code on every line.

For questions like these I recommend using a search engine or posting on a more programming friendly site.

share|improve this answer
I really don't understand what you I only need to use IFS (by theway, we use "FS")? – marcos ruiz May 18 '14 at 16:19
could you please suggest me "a more programming friendly site"? thanks for your help – marcos ruiz May 19 '14 at 7:07

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.