#!/usr/bin/perl
use strict;
use warnings;

# listdir:
# This script lists the files in the specified directory
# It gives the info from 'stat' (i.e. similar to 'ls -l')
# Cameron Hayne (macdev@hayne.net)  May 2004

# If no command-line argument, use the current directory
my $dirname = scalar(@ARGV) >= 1 ? $ARGV[0]: ".";

# function declarations
sub list_directory($);

MAIN:
{
    list_directory($dirname);
}
exit;


#----- FUNCTIONS -----

sub printable($)
{
    my ($str) = @_;

    # replace anything other than normal characters with a question mark
    $str =~ s/[^\w\d.\- ]/?/g;
    return $str;
}

sub time_as_date($)
{
    my ($time) = @_;

    my $date = localtime($time);
    return $date;
}

sub print_info($$)
{
    my ($dirname, $filename) = @_;

    use File::stat;
    my $info = stat("$dirname/$filename")
        or warn "Can't stat file $filename: $!\n" and return;

    # see 'man stat' for the meaning of the following fields
    my $name = printable($filename);
    my $ino   = $info->ino;     # inode
    my $mode  = $info->mode;    # permissions etc
    my $nlink = $info->nlink;   # number of links to this file/directory
    my $uid   = $info->uid;     # user ID of owner
    my $gid   = $info->gid;     # group ID
    my $size  = $info->size;    # size in bytes
    my $atime = $info->atime;   # time of last access (seconds since epoch)
    my $mtime = $info->mtime;   # time of last data modification
    my $ctime = $info->ctime;   # time of last file status change

    # discard file type info from 'mode' and put in usual numeric format
    my $perms = sprintf("%04o", $mode & 07777);

    # convert times (in seconds since the epoch) to date strings
    my $adate = time_as_date($atime);
    my $mdate = time_as_date($mtime);
    my $cdate = time_as_date($ctime);

    # print out the desired fields in tab-separated format
    print "$name\t$uid\t$gid\t$perms\t$mdate\n";
}

sub list_directory($)
{
    my ($dirname) = @_;

    # open the directory and call 'print_info()' for each file/sub-directory
    opendir(DIR, $dirname) or die "can't opendir $dirname: $!";
    while (defined(my $filename = readdir(DIR)))
    {
        next if $filename =~ /^\.\.?$/;     # skip . and ..
        print_info($dirname, $filename);
    }
    closedir(DIR);
}

