The Problem
As a programmer I am always searching for elegant ways how to accomplish certain things. One of the last tasks was to parse the /etc/passwd file of a linux box. Of course there are multiple ways how to do this, but the Java8 way seems to be a cool solution.
The Solution
The Program consists of two classes. The first one is the 'PwdUser' class which represents one single entry in the passwd file:
{
public String userid;
public String password;
public Integer uid;
public Integer gid;
public String fullname;
public String homedir;
public String shell;
public PwdUser(String pwdline)
{
String[] values = pwdline.split(":");
if(values.length != 7)
{
throw new IllegalArgumentException("Line must have 7 fields");
}
this.userid = values[0];
this.password = values[1];
this.uid= Integer.parseInt(values[2]);
this.gid= Integer.parseInt(values[3]);
this.fullname = values[4];
this.homedir = values[5];
this.shell = values[6];
}
}
As you see - you can call the constructor with a full line from the passwd file ant the line is slitted up into separate variables. (Errorchecking could be better - but this example is more for educational purposes)
The second class is the main class:
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Test
{
public static void main(String[] args)
{
// Read the file
try (Stream<String> stream = Files.lines(Paths.get("/etc/passwd")))
{
// Yeah - Java8 read, filter and instantiante on one line of code !
ArrayList<PwdUser> users = stream.map(PwdUser::new)
.filter(u -> !u.shell.equals("/bin/false"))
.filter(u -> !u.shell.equals("/usr/sbin/nologin"))
.collect(Collectors.toCollection(ArrayList::new));
// Do something with your users ...
for (PwdUser u : users)
{
System.out.println(u.userid);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
This is where the magic happens:
- The file is opened within the try - which means that the JVM closes it automatically (try-with-ressources)
- Within the try block we have the stream of the file which is processed as follows:
- Create a PwdUser for every line in the file
- Remove all objects which are not allowed to log into the system (This is indicated by a shell does not equal to /bin/false and also not to /usr/sbin/nologin
- Grab the remeaning ones an put them into a new ArrayList
- Iterate over the ArrayList and process the objects
Neat - isn't it ?