valerydolce has asked for the wisdom of the Perl Monks concerning the following question:

Hi All I'm trying to list all users' home directories from a linux host. All the directories are located in '/home.itvm' but the are additional home directories under a folder named DUMMIES, for example Dummy1, Dummy2

#Example /home.it20/user1 /home.it20/DUMMIES /home.it20/DUMMIES/Dummy1 /home.it20/DUMMIES/Dummy2

Please what is the regular expression that will allow me to match all these directories? Can we consider DUMMIES as a home directory ?

Replies are listed 'Best First'.
Re: List all Users Directory
by hippo (Archbishop) on Dec 13, 2016 at 22:04 UTC
    I'm trying to list all users' home directories from a linux host.

    You don't need a regex for that, you can get it directly from /etc/passwd. eg:

    perl -F: -nae 'print "$F[0] has home dir $F[5]\n" if $F[5];' /etc/pass +wd

    Of course, you can change the test in there to be a regex match if you want to restrict the output, but it might be simpler to restrict it by UID range or similar. This should get you started anyway.

      > you can get it directly from /etc/passwd

      Unless the system uses LDAP :-)

      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: List all Users Directory
by eyepopslikeamosquito (Archbishop) on Dec 14, 2016 at 07:46 UTC

    Be aware that Perl has a number of built-in functions relating to users and groups, for example: getlogin, getpwnam, getgrent. See Perl functions for fetching user and group info.

    The simple code below, while perhaps not meeting your specific requirements, lists all users on a Linux box (including their home directories and other properties) by using the Perl builtin getpwent function:

    use strict; use warnings; while ( my ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $home, $shell) = getpwent ) { print <<"ALL_USER_ATTRS"; name = $name passwd = $passwd uid = $uid gid = $gid quota = $quota comment = $comment gcos = $gcos home = $home shell = $shell ALL_USER_ATTRS }

    See also Re: adding a group to the Unix System for example code that calls getpwnam.

Re: List all Users Directory
by kcott (Archbishop) on Dec 14, 2016 at 06:30 UTC

    G'day valerydolce,

    Here's the steps you need for each line.

    1. Match the start of the line.
    2. Match the first / and everything up to, but not including, the second /.
    3. Match a / followed by DUMMIES (one or zero times with no backtracking).
    4. Match a /.
    5. Start capture.
    6. Match anything that isn't a / (one or more times non-greedily).
    7. End capture.
    8. Match the end of the line (before newline).

    If the match was successful, $1 will contain 'user1', 'Dummy1', etc.

    There a number of ways to implement this. I'll leave you to choose whichever you want.

    Information on how to do everything described above can be found in perlre.

    Update: I made the final step a little more specific by adding "(before newline)". Also fixed a typo: s/with contain/will contain/.

    — Ken

Re: List all Users Directory
by haukex (Archbishop) on Dec 15, 2016 at 10:02 UTC

    Hi valerydolce,

    There are better solutions than the following (e.g. eyepopslikeamosquito's post), but since nobody has mentioned it yet, for completeness here are two solutions that actually access the file system and list directories. One of the problems with this is that there may be stray directories present that do not map to users; I've also hardcoded the "DUMMIES" name. In the second solution, I'm also showing something that I would normally recommend against: using a regex on a pathname, in this case it might be justified if you know you'll only be working with *NIX pathnames.

    use Path::Class qw/file dir/; my @homes = ( grep({$_->is_dir && $_->basename ne 'DUMMIES'} dir('/home')->child +ren), grep({$_->is_dir} dir('/home/DUMMIES')->children) ); use File::Spec::Functions qw/splitdir/; # core module my @homes2 = ( grep({-d && (splitdir($_))[-1] ne 'DUMMIES'} glob '/home/*'), #OR: grep({-d && !m#/DUMMIES$#} glob '/home/*'), grep({-d} glob '/home/DUMMIES/*') );

    Hope this helps,
    -- Hauke D

Re: List all Users Directory
by Marshall (Canon) on Dec 14, 2016 at 21:22 UTC