I need to develop a perl script that will generate a formatted listing of any user without a home directory and any home directory that is not attached to a user. For example, if I used the script below to read in the systems users how would I print out which users do not have a home directory based on theirs UID:

open (USERS, '-|' , 'getent passwd' ) or die $!;
    @passwd_entries = <USERS>;
    close USERS;

And if I read in the system's home directories with the script below how would I print out which directories do not have users attached to them?

open (HOMES, '-|' , 'ls /home' ) or die $!;
    @home_dirs = <HOMES>;
    close HOMES;
  • Is it an assumption, then, that every home directory is under /home? Root’s commonly is not. – Jeff Schaller May 14 '18 at 20:53
  • Yes that’s the assumption, all the home directories I’m working with are under /home – Pat May 15 '18 at 13:47
  • The code in the question generates two arrays the first one with all the users and the second one with all the directories. For the users array how do I print out the entries without /home directories and for the /home array how do I print out the directories without users. I would assume that UID's in the passwd file will have something to do with generating the appropriate results. I just don't know how – Pat May 16 '18 at 0:08

If you're happy with a bash solution, this will write out the list of users without home directories in /home, and the directories under /home that have no users in the password database:

comm -3 <(getent passwd | cut -d: -f6 | sort -u) <(ls -d1 /home/*)

It has been a while since I have been using Perl, but I came up with something that may get you where you need to go. Since you are using Perl, we will avoid using any bash commands:

use strict;
use warnings;

# this will get all users and homedirs directly
while(my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwent()){
    my $dirstate;
    # this will check if $dir exists and is a directly
    if (-e $dir and -d $dir) {
        $dirstate = 'homeexists';
    } else {
        $dirstate = 'nohome';

    # here you have knowledge of which home dirs do and do not exist in $dirstate
    print "$name:$uid:$gid:$gcos:$dir:$shell:$dirstate\n";

Or, if you really wanted to use bash commands, this one liner does close to the same:

getent passwd | awk -F: '{printf "%s %s\n",$1,$6}' | while read i; do home=($i); if [ ! -d ${home[1]} ]; then home+=("nohome") ; fi ; echo ${home[@]}; done

As for which home directories exist that do not have users, since home directories can be anywhere on the filesystem I am not sure how best to accomplish that. You could use ls to see what is in /home and compare to the users you get from getent, if that is what you need to do.

  • open (HOMES, '-|' , 'ls /home' ) or die $!; @home_dirs = <HOMES>; close HOMES; This saves all the /home directories I'll be analyzing in an array. How do I print out the once that don't have users? – Pat May 15 '18 at 23:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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