Code:
#!/usr/bin/perl
use strict;
use warnings;
#use File::stat;
use Fcntl ':mode';
use POSIX 'strftime';
our($max_nlink, $max_uid, $max_gid, $max_size)=(0,0,0,0);
our(%type, %exec, %perm, %nlink, %username, %groupname, %modtime, %filesize, %filename);
my(@x, @arg);
my($l, $F, $a, $h)=(0,0,0,0);
my($dev, $inode, $mode, $nlink, $uid, $gid, $rdev, $size, $time, $mtime, $ctime, $blksize, $blocks);
foreach (@ARGV){
if(/^-/){
if(/l/){ $l =1 ;}
if(/F/){ $F =1 ;}
if(/a/){ $a =1 ;}
if(/h/){ $h =1 ;}
}
else {
push(@arg, $_);
}
}
if(scalar(@arg)==0){
push(@arg, '.');
}
foreach (@arg){
my $argment = $_;
if(-e $argment || die "$!\n"){
if(-d $argment){
if($argment ne '/'){
$argment =~ s/\/$//;
}
opendir(D, "$argment") || die "$!\n";
@x = readdir(D);
}
else{
push (@x, $argment) ;
}
}
foreach (@x){
my $file = $_;
my $fullpathname;
if(-d $argment){
$fullpathname = $argment.'/'.$file; # need full path name to get the info unless traversing the current dir.
}
else {
$fullpathname = $file;
}
($dev, $inode, $mode, $nlink, $uid, $gid, $rdev, $size, $time, $mtime, $ctime, $blksize, $blocks) = lstat($fullpathname);
$type{$file} = (type($fullpathname))[0]; # sub call to get the file type.
$exec{$file} = (type($fullpathname))[1]; # sub call to get the file type.
$perm{$file} = perm($mode); # sub call to get the permission info.
$nlink{$file} = $nlink; # link count
$username{$file} = getpwuid($uid); # convert uid to user name
$groupname{$file} = getgrgid($gid); # convert gid to group name
$modtime{$file} = strftime("%Y-%m-%d %H:%M", localtime($mtime)); # convert mtime in second to 'Y-M-D H-M' format
$filesize{$file} = filesize($h, $size); # sub call to calculate file size
filename($F, $l, $file, $fullpathname); # sub call to append /, @ or * if needed.
fieldlen($nlink{$file}, $username{$file}, $groupname{$file}, $filesize{$file}); # sub call to calculate the field size.
}
if(-d $argment){
print "$argment".":\n";
}
else {
print "\n";
}
disp($l, $F, $a, $h, @x);
if(-d $argment){
closedir(D);
}
undef(@x);
}
sub perm { # subroutine to convert the permission to rwx format.
my $mode = shift(@_);
my $p = sprintf("%04o", S_IMODE($mode));
my (@tmp, $perm, $t);
@tmp = split(//, $p);
for(0..2) {
$t = pop(@tmp);
SWITCH: {
($t == 0) && do {unshift(@tmp, '---') ; last SWITCH; };
($t == 1) && do {unshift(@tmp, '--x') ; last SWITCH; };
($t == 2) && do {unshift(@tmp, '-w-') ; last SWITCH; };
($t == 3) && do {unshift(@tmp, '-wx') ; last SWITCH; };
($t == 4) && do {unshift(@tmp, 'r--') ; last SWITCH; };
($t == 5) && do {unshift(@tmp, 'r-x') ; last SWITCH; };
($t == 6) && do {unshift(@tmp, 'rw-') ; last SWITCH; };
($t == 7) && do {unshift(@tmp, 'rwx') ; last SWITCH; };
}
}
$t = pop(@tmp);
if($t==1 || $t==3 || $t==5 || $t==7){ # sticky
(substr($tmp[2],2,1) eq 'x') ? substr($tmp[2],2,1, 't') : substr($tmp[2],2,1, 'T');
}
elsif($t==2 || $t==3 || $t==6 || $t==7){ # sgid
(substr($tmp[1],2,1) eq 'x') ? substr($tmp[1],2,1, 's') : substr($tmp[1],2,1, 'S');
}
elsif($t== 4 || $t==5 || $t==6 || $t==7){ # suid
(substr($tmp[0],2,1) eq 'x') ? substr($tmp[0],2,1, 's') : substr($tmp[0],2,1, 'S');
}
$perm = join('', @tmp);
return $perm ;
}
sub type { # subroutine to find the file type
my $file = shift(@_);
my $exec = 0;
my $type;
(-l $file) && do {$type = 'l'} || # symbolic link
(-b $file) && do {$type = 'b'} || # block device
(-c $file) && do {$type = 'c'} || # character device
(-p $file) && do {$type = 'p'} || # pipe
(-S $file) && do {$type = 's'} || # socket
(-d $file) && do {$type = 'd'} || # directory
do {$type = '-'}; # others
(-x $file) && !(-d $file) && do {$exec = 1} ;
return ($type, $exec);
}
sub filesize { # subroutine to convert the file size to in K/M/G.
my ($h, $size) = @_;
my $filesize = $size;
my $len=length($filesize);
if($h && $l){
if($len > 9){
$filesize = substr($size/1000000000, 0, 3);
$filesize =~ s/\.$//;
$filesize = $filesize.'G';
}
elsif($len > 6){
$filesize = substr($size/1000000, 0, 3);
$filesize =~ s/\.$//;
$filesize = $filesize.'M';
}
elsif($len > 3){
$filesize = substr($size/1000, 0, 3);
$filesize =~ s/\.$//;
$filesize = $filesize.'K';
}
}
return $filesize;
}
sub filename { # subroutine to append /, @ or * if needed.
my ($F, $l, $file, $fullpathname) = @_;
my ($tgt);
$filename{$file} = $file;
if($F){
if (-l $fullpathname){
$filename{$file} = $file.'@';
}
elsif(-d $fullpathname){
$filename{$file} = $file.'/';
}
elsif (-f $fullpathname && $exec{$file}){
$filename{$file} = $file.'*';
}
}
if($l && -l $fullpathname){
$filename{$file} = "$file".' -> '.readlink($fullpathname) ;
}
return $filename{$file};
}
sub fieldlen { # subroutine to find the longest field for each items to determie the field size upon the printing.
my ($nlink, $uid, $gid, $size) = @_;
my($len);
$len = length($nlink);
($len > $max_nlink) && do {$max_nlink = $len};
$len = length($uid);
($len > $max_uid) && do {$max_uid = $len};
$len = length($gid);
($len > $max_gid) && do {$max_gid = $len};
$len = length($size);
($len > $max_size) && do {$max_size = $len};
}
sub disp { # subroutine to display the result.
my ($l, $F, $a, $h, @x) = @_;
my $flag = $l.$F.$a.$h ;
SWITCH: {
($flag eq '0000') && do { shrt_prn(@x) ; last SWITCH; };
($flag eq '0001') && do { shrt_prn(@x) ; last SWITCH; };
($flag eq '0010') && do { shrt_all_prn(@x) ; last SWITCH; };
($flag eq '0011') && do { shrt_all_prn(@x) ; last SWITCH; };
($flag eq '0100') && do { shrt_prn(@x) ; last SWITCH; };
($flag eq '0101') && do { shrt_prn(@x) ; last SWITCH; };
($flag eq '0110') && do { shrt_all_prn(@x) ; last SWITCH; };
($flag eq '0111') && do { shrt_prn(@x) ; last SWITCH; };
($flag eq '1000') && do { long_prn(@x) ; last SWITCH; };
($flag eq '1001') && do { long_prn(@x) ; last SWITCH; };
($flag eq '1010') && do { long_all_prn(@x) ; last SWITCH; };
($flag eq '1011') && do { long_all_prn(@x) ; last SWITCH; };
($flag eq '1100') && do { long_prn(@x) ; last SWITCH; };
($flag eq '1101') && do { long_prn(@x) ; last SWITCH; };
($flag eq '1110') && do { long_all_prn(@x) ; last SWITCH; };
($flag eq '1111') && do { long_all_prn(@x) ; last SWITCH; };
}
}
sub shrt_prn {
foreach (@_){
if(!/^\./){ ## other than . and ..
print "$filename{$_}\n";
}
}
}
sub shrt_all_prn {
foreach (@_){ ## all printed out
print "$filename{$_}\n";
}
}
sub long_prn {
foreach (@_){
if(!/^\./){ ## other than . and ..
printf "%10s %${max_nlink}s %${max_uid}s %${max_gid}s %${max_size}s %15s %-s\n", $type{$_}.$perm{$_}, $nlink{$_}, $username{$_}, $groupname{$_}, $filesize{$_}, $modtime{$_}, $filename{$_};
}
}
}
sub long_all_prn {
foreach (@_){
printf "%10s %${max_nlink}s %${max_uid}s %${max_gid}s %${max_size}s %15s %-s\n", $type{$_}.$perm{$_}, $nlink{$_}, $username{$_}, $groupname{$_}, $filesize{$_}, $modtime{$_}, $filename{$_};
}
}
Bookmarks