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

I'm pretty sure I've seen that somewhere, but I can't find it now. Is there a subroutine/module I could steal to turn Unix file permissions into the format used by ls -l?

0755 becomes rwxr-xr-x, 04700 turns into rws------. Any pointers appreciated!

Replies are listed 'Best First'.
Re: Turning 0755 into rwxr-xr-x
by ikegami (Patriarch) on Aug 11, 2005 at 06:42 UTC

    I found Stat::lsMode on CPAN. Looks like it will do the trick. Example usage:

    use Stat::lsMode; Stat::lsMode->novice(0); print format_perms(0755), "\n"; print format_perms(04700), "\n";
Re: Turning 0755 into rwxr-xr-x
by davido (Cardinal) on Aug 11, 2005 at 06:42 UTC

    Stat::lsMode to the rescue...

    From its synopsis:

    $permissions = format_perms(0644); # Produces just 'rw-r--r--'

    Dave

      Exactly what I was looking for, thanks guys!
Re: Turning 0755 into rwxr-xr-x
by gellyfish (Monsignor) on Aug 11, 2005 at 09:01 UTC

    Just in case you wondered how you might go about doing this yourself without using a module:

    sub mode_to_string { my ($mode) = @_; + my @str_mode; + for (0 .. 2) { unshift @str_mode, $mode & 1 ? 'x':'-'; unshift @str_mode, $mode & 2 ? 'w':'-'; unshift @str_mode, $mode & 4 ? 'r':'-'; $mode = $mode >> 3; } + return join '', @str_mode; } + print mode_to_string(0647);
    Of course you are almost certainly better off using the module as it will handle the setuid, setgid and sticky bits properly, but this is by way of example how things are often not as tricky as they seem.

    /J\

      This isn't working properly for me. If I give the sub 755, it produces -wxrw--wx. Very different from rwxr-xr-x.

      So I revised the sub a bit:

      sub split_mode_to_string { my @sections = reverse split '', $_[0]; my @str_mode; for my $mode (@sections) { unshift @str_mode, $mode & 1 ? 'x':'-'; unshift @str_mode, $mode & 2 ? 'w':'-'; unshift @str_mode, $mode & 4 ? 'r':'-'; } return join '', @str_mode; }

      Which gives the right permissions for 755. As well as all of the other tests I tried (001, 010, 100, et cetera). I think the issue with the original sub is that 755 shifted right by 3 is not 75 -- it's 94.

        Er, well you would be right if you weren't missing the fact that the mode here is actually an octal number that has to begin with a zero in Perl - that is to say 0755 will work fine whereas the 755 will not.

        This is probably even easier to understand if you do:

        my $mode = (stat('.'))[2] & 07777; print $mode ,"\n"; printf "%o\n", $mode ; print mode_to_string($mode);
        Where the 07777 is a mask to remove the filetype information from the mode (as described in perlfunc).

        /J\