Databases
cancel
Showing results for 
Search instead for 
Did you mean: 

perl and the mode element of stat

eric stewart
Frequent Advisor

perl and the mode element of stat

Does anyone know how to take the mode element and convert it to the same information as is in the ls command?
Here is ls:
>ls -l
total 8
drwxr-xr-x 2 estewar1 users 96 Dec 6 15:55 eric
-rw-r--r-- 1 estewar1 users 949 Oct 16 13:08 home_monitor
-rw-r--r-- 1 estewar1 users 38 Oct 16 13:08 lpl
-rw-r--r-- 1 estewar1 users 26 Oct 16 13:08 lpp
-rwxr-xr-x 1 estewar1 users 874 Dec 6 15:43 sam.k

Here is the output from my perl program:
>./sam.k
33261 1 estewar1 users 336 Sep 16 13:09 .eric.df
16877 2 estewar1 users 96 Nov 06 15:55 eric
33188 1 estewar1 users 949 Sep 16 13:08 home_monitor
33188 1 estewar1 users 38 Sep 16 13:08 lpl
33188 1 estewar1 users 26 Sep 16 13:08 lpp
33261 1 estewar1 users 874 Nov 06 15:43 sam.k
TIA
From a beginner of perl!
Good help is easy to find within forums
2 REPLIES
Leslie Chaim
Regular Advisor

Re: perl and the mode element of stat

Eric,

The mode returned from the stat function includes the file permissions AND the type. Therefore, you have to mask it.

The following one liner illustrates this:

perl -le 'printf STDOUT "perms are %04o\n", (stat ("$filename"))[2] & 07777'

Hope this helps

Leslie
If life serves you lemons, make lemonade
Gregory Fruth
Esteemed Contributor

Re: perl and the mode element of stat

The module Stat::lsMode (available at CPAN) does the conversion
you want. See http://www.perl.com/CPAN-local/README.html.
From the documentation:

use Stat::lsMode;
$file = "somefile.foo";
$mode = (stat $file)[2];
$permissions = format_mode($mode);
# $permissions is now something like `drwxr-xr-x'

$permissions = file_mode($file); # Same as above

If you don't want to install Stat:lsMode, you can also use the
POSIX module (already included in the Perl core module
set) to get the constants you need and build the string yourself:

use POSIX;

$s = (stat("somefile.foo"))[2];

$type = "b" if (S_ISBLK($s));
$type = "c" if (S_ISCHR($s));
$type = "d" if (S_ISDIR($s));
$type = "p" if (S_ISFIFO($s));
$type = "-" if (S_ISREG($s));
# note: "use POSIX" doesn't seem to provide constants for types
# "n" "s" or "l"
# note: if the file is a symlink (type "l"), you might
# want to use lstat() instead of stat()

@modes = qw(- - - - - - - - -);
$modes[0] = "r" if ($s & S_IRUSR);
$modes[1] = "w" if ($s & S_IWUSR);
$modes[2] = "x" if ($s & S_IXUSR);
$modes[3] = "r" if ($s & S_IRGRP);
$modes[4] = "w" if ($s & S_IWGRP);
$modes[5] = "x" if ($s & S_IXGRP);
$modes[6] = "r" if ($s & S_IROTH);
$modes[7] = "w" if ($s & S_IWOTH);
$modes[8] = "x" if ($s & S_IXOTH);
# note: "use POSIX" doesn't seem to provide the constant for
# S_ISVTX (the so-called "sticky" bit)

if ($s & S_ISUID) {$modes[2] = ($s & S_IXUSR) ? "s" : "S";}
if ($s & S_ISGID) {$modes[5] = ($s & S_IXGRP) ? "s" : "S";}

print $type . join("", @modes) . "somefile.foo\n";
print `ls -l somefile.foo`;