Article 344 of alt.sources:
Path: lightnin!rwsys!utacfd.uta.edu!news.oc.com!mercury.unt.edu!cs.utexas.edu!wupost!uunet!mcsun!uknet!pavo.csi.cam.ac.uk!nntp-serv.cam.ac.uk!tdw
From: [email protected] (Tim Wilson)
Newsgroups: alt.sources
#Subject: Another stat program (perl script)
Message-ID: <[email protected]>
Date: 5 Oct 92 12:43:26 GMT
Sender: [email protected] (USENET news)
Organization: University of Cambridge Computer Laboratory, UK
Lines: 307
Nntp-Posting-Host: ramsey.cl.cam.ac.uk

Here's another stat command.

Use the -l flag to examine symbolic links (instead of the linked-to file).

This version of stat one has two output formats.
The default is human-readable, eg

$ stat stat
stat
       device          0x5526
       inode           23068           0x5a1c
       mode            -r-xr-xr-x      0100555
       nlink           1
       owner           tdw
       group           private
       rdev            -1
       size            6707
       atime           Mon Oct  5 12:31:57 1992
       mtime           Mon Oct  5 11:53:48 1992
       ctime           Mon Oct  5 11:53:48 1992
       blksize         8192
       blocks          14

but there is also a numeric output format that is useful for forther
processing, eg

$ stat -n stat
stat 0x5526 0x5a1c 0100555 1 1007 19 0xffffffff 6707 718284717 718282428 718282428 8192 14

The fields are:
device inode mode nlink uid gid rdev size {a,m,c}time blocksize blocks.

I hope someone finds this useful.
If you have any comments or suggestions, please let me know.

Tim
--
Tim Wilson   [email protected]   University of Cambridge Computer Laboratory, UK
--- CUT HERE -----------------------------------------------------------------
# /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#               "End of shell archive."
# Contents:  stat
# Wrapped by [email protected] on Mon Oct  5 12:31:57 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'stat' -a "${1}" != "-c" ; then
 echo shar: Will not clobber existing file \"'stat'\"
else
echo shar: Extracting \"'stat'\" \(6707 characters\)
sed "s/^X//" >'stat' <<'END_OF_FILE'
X#!/usr/bin/perl
X#
X# Last edited: Mon Oct  5 11:48:02 1992 by Tim Wilson
X# $Id: stat,v 1.1 1992/10/05 10:53:13 tdw Exp $
X#
X# Stat(2) files and print results.
X#
X# Usage: stat [-?] [-l] [-n] [-h] [--] files...
X#
X#  -l: use lstat(2) instead of stat(2)
X#  -n: print output in numeric format (instead of readable format)
X#  -h: if in numeric format, also print header line
X#  -?: print help message
X#  --: remaining arguments are file names
X#
X######################################################################
X#
X# Copyright (C) 1992 T D Wilson.  All rights reserved.
X#
X# Permission to copy without fee all or part of this material is
X# granted provided that the copies are not made or distributed for
X# direct commercial advantage, the copyright notice and the title and
X# date appear, and notice is given that copying is by permission of
X# the author.  To copy otherwise, or to republish, requires specific
X# permission.
X#
X# T D Wilson makes no representations about the suitability of this
X# software for any purpose.  It is provided "as is" without express or
X# implied warranty.
X#
X######################################################################
X#
X# Modification summary:
X#   5 Oct 1992 Tim Wilson      Altered comments; posted to
X#                              alt.sources.  Revision 1.1.
X#  11 Jul 1991 Tim Wilson      Created.
X#
X# Tim Wilson, University of Cambridge Computer Laboratory, UK.
X# [email protected]
X#
X
Xsub usage {
X       die "Usage: $progname [-l] [-n] [-h] [--] files...\n";
X}
X
Xsub Lstat {
X    ($st_dev,$st_ino,$st_mode,$st_nlink,$st_uid,$st_gid,$st_rdev,$st_size,
X       $st_atime,$st_mtime,$st_ctime,$st_blksize,$st_blocks) = lstat(shift(@_));
X}
X
Xrequire "stat.pl";
Xrequire "ctime.pl";
X
X######################################################################
X#
X# p_perm -- Return part permissions symbolically
X#
X#  perm:       Permissions.  Only the low three bits are significant
X#  extra:      Extra bit to be encoded with execute (suid, sgid, sticky)
X#  c:          Character to be used instead of `x' (`s' or `t')
X#
X# Returns -- three character string
X#
X# Side effects -- Output
X#
X######################################################################
X
Xsub p_perm {
X       local ($perm,$extra,$c) = @_;
X       local ($lower,$upper) = ($c, $c);
X       local ($result);
X       $lower =~ tr/ST/st/; # Guaranteed lower case `s' or `t'
X       $upper =~ tr/st/ST/; # Guaranteed upper case `S' or `T'
X
X       $result = ($perm & 04) ? "r" : "-";
X       $result .= ($perm & 02) ? "w" : "-";
X       # Want 2D array; do index arithmetic ourselves
X       $result .= ("-", "x", $upper, $lower)[!!$extra * 2 + ($perm & 01)];
X}
X
X
X######################################################################
X#
X# p_mode -- Return symbolic $st_mode (and/or memorized stat structure)
X#
X#  Arguments are global variables.  Ahem!
X#
X# Returns -- ten character string
X#
X# Side effects -- Output
X#
X######################################################################
X
Xsub p_mode {
X       local ($result);
X       # First letter according to type of file
X       TYPE: {
X               -p _ && do {$result = "p"; last TYPE;};
X               -c _ && do {$result = "c"; last TYPE;};
X               -d _ && do {$result = "d"; last TYPE;};
X               -b _ && do {$result = "b"; last TYPE;};
X               -l $file && do {$result = "l"; last TYPE;};# lstat problems
X               -f _ && do {$result = "-"; last TYPE;};
X               -S _ && do {$result = "s"; last TYPE;};
X               warn ("unknown type of file, mode %#o\n", $st_mode);
X               $result = "?";
X       }
X
X       $result .= &p_perm ($st_mode >> 6, -u _, "s");  # User
X       $result .= &p_perm ($st_mode >> 3, -g _, "s");  # Group
X       $result .= &p_perm ($st_mode >> 0, -k _, "t");  # Others
X}
X
X
X######################################################################
X#
X# uid, gid -- Convert numeric uid, gid to symbolic
X#
X#  arg:                numeric id
X#
X# Returns -- Name associated with id if found, else number
X#
X# Side effects -- Accesses /etc/passwd or replacement
X#
X######################################################################
X
Xsub uid {
X       local ($uid) = @_;
X       local ($name) = getpwuid ($uid);
X
X       defined ($name) ? return $name : return $uid;
X}
X
Xsub gid {
X       local ($gid) = @_;
X       local ($name) = getgrgid ($gid);
X
X       defined ($name) ? return $name : return $gid;
X}
X
X
X######################################################################
X#
X# verbstat -- Print $st_* variable (and/or remembered stat structure)
X#             in multiline verbose format
X#
X#  Arguments are global variables.  Ahem!
X#
X# Returns -- nothing
X#
X# Side effects -- Output
X#
X######################################################################
X
Xsub verbstat {
X       local ($atime, $mtime, $ctime)
X               = (&ctime ($st_atime), &ctime ($st_mtime), &ctime ($st_ctime));
X       local ($mode) = &p_mode;
X
X       printf ("%s\n", $file);
X       printf ("\tdevice\t\t%#x\n", $st_dev);
X       printf ("\tinode\t\t%d\t\t%#x\n", $st_ino, $st_ino);
X       printf ("\tmode\t\t%s\t%#o\n", &p_mode, $st_mode);
X       printf ("\tnlink\t\t%d\n", $st_nlink);
X       printf ("\towner\t\t%s\n", &uid ($st_uid));
X       printf ("\tgroup\t\t%s\n", &gid ($st_gid));
X       printf ("\trdev\t\t%d\n", $st_rdev);
X       printf ("\tsize\t\t%d\n", $st_size);
X       chop ($atime);
X       chop ($mtime);
X       chop ($ctime);
X       printf ("\tatime\t\t%s\n\tmtime\t\t%s\n\tctime\t\t%s\n",
X               $atime, $mtime, $ctime);
X       printf ("\tblksize\t\t%d\n", $st_blksize);
X       printf ("\tblocks\t\t%d\n", $st_blocks);
X}
X
X
X######################################################################
X# Main program
X######################################################################
X
X$_ = $0;
X$progname = m|.*/([^/]+)| ? $1 : $_;
X
X
X$opt_lstat = 0;                                # If true use lstat not stat
X$opt_header = 0;                       # Add header line
X$opt_numeric = 0;                      # One-line numeric format
X
X# No switch clustering with this simple parser
X
XSWITCH:
Xwhile ($_ = shift) {
X       /^-\?/ && &usage;                       # stat -? ... gives usage
X       /^--$/ && last SWITCH;                  # -- terminates switches
X       /^-l$/ && ($opt_lstat = 1, next SWITCH);
X       /^-h$/ && ($opt_header = 1, next SWITCH);
X       /^-n$/ && ($opt_numeric = 1, next SWITCH);
X
X       unshift (ARGV, $_);             # We are looking at the first file
X       last SWITCH;
X}
X
X($#ARGV < $[) && &usage;               # Must have at least one arg
X
X
X# Print out header if requested and numeric format
X
X$opt_numeric && $opt_header && print "dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks\n";
X
X
X# Stat remaining args and print result
X
Xforeach $file (@ARGV) {
X       if ($opt_lstat) {
X               &Lstat ($file);
X       } else {
X               &Stat ($file);
X       }
X
X       if (defined ($st_dev)) {
X               if ($opt_numeric) {
X                       #       fn  dev ino md  nl ud gd rdv siz atm mtm ctm bks nbk
X                       printf "%s %#x %#x %#o %d %d %d %#x %ld %ld %ld %ld %d %d\n",
X                       $file,
X                       $st_dev, $st_ino, $st_mode, $st_nlink,
X                       $st_uid, $st_gid,
X                       $st_rdev, $st_size,
X                       $st_atime, $st_mtime, $st_ctime,
X                       $st_blksize, $st_blocks;
X               } else {
X                       &verbstat;
X               }
X       } else {
X               $opt_lstat ?
X                       warn $file, ": Can't lstat\n" :
X                       warn $file, ": Can't stat\n";
X       }
X}
X
X# End of stat
END_OF_FILE
if test 6707 -ne `wc -c <'stat'`; then
   echo shar: \"'stat'\" unpacked with wrong size!
fi
chmod +x 'stat'
# end of 'stat'
fi
echo shar: End of shell archive.
exit 0
--
Tim Wilson   [email protected]   University of Cambridge Computer Laboratory, UK