1

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:

users.txt:

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

1
  • 7
    Google and do your homework. :) May 15, 2014 at 16:33

3 Answers 3

3

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;
3
  • 1
    The third awk is incorrect. It'll include the ` ;` from the end of the lines.
    – Oli
    May 16, 2014 at 20:29
  • If I can use sed I could do path=awk -F: '{print $3}' users.txt | sed 's/;$//';
    – user257256
    May 16, 2014 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? May 18, 2014 at 16:31
2

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
done

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

9
  • 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. May 15, 2014 at 21:08
  • @glennjackman sure, just the question asks for it explicitly.
    – Oli
    May 15, 2014 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 May 18, 2014 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, 2014 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 May 20, 2014 at 8:46
1

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

#!/bin/bash
IFS=$','
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.

2
  • I really don't understand what you mean...do I only need to use IFS (by theway, we use "FS")? May 18, 2014 at 16:19
  • could you please suggest me "a more programming friendly site"? thanks for your help May 19, 2014 at 7:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .