start page | rating of books | rating of authors | reviews | copyrights

Perl Cookbook

Perl CookbookSearch this book
Previous: 9.11. Program: symirror Chapter 9
Directories
Next: 10. Subroutines
 

9.12. Program: lst

Have you ever wondered what the newest or biggest files within a directory are? The standard ls program has options for listing out directories sorted in time order (the -t flag) and for recursing into subdirectories (the -R flag). However, it pauses at each directory to display the sorted contents of just that directory. It doesn't descend through all the subdirectories first and then sort everything it finds.

The following lst program does that. Here's an example using its -l flag to get a long listing:

% lst -l /etc 



12695 0600      1     root    wheel      512 Fri May 29 10:42:41 1998 



 



    /etc/ssh_random_seed



 



12640 0644      1     root    wheel    10104 Mon May 25  7:39:19 1998 



 



    /etc/ld.so.cache



 



12626 0664      1     root    wheel    12288 Sun May 24 19:23:08 1998 



 



    /etc/psdevtab



 



12304 0644      1     root     root      237 Sun May 24 13:59:33 1998 



 



    /etc/exports



 



12309 0644      1     root     root     3386 Sun May 24 13:24:33 1998 



 



    /etc/inetd.conf



 



12399 0644      1     root     root    30205 Sun May 24 10:08:37 1998 



 



    /etc/sendmail.cf



 



18774 0644      1     gnat  perldoc     2199 Sun May 24  9:35:57 1998 



 



    /etc/X11/XMetroconfig



 



12636 0644      1     root    wheel      290 Sun May 24  9:05:40 1998 



 



    /etc/mtab



 



12627 0640      1     root     root        0 Sun May 24  8:24:31 1998 



 



    /etc/wtmplock



 



12310 0644      1     root  tchrist       65 Sun May 24  8:23:04 1998 



 



    /etc/issue



 ....

/etc/X11/XMetroconfig showed up in the middle of the listing for /etc because it wasn't just for /etc , but for everything within that directory, recursively.

Other supported options include sorting on read time instead of write time using -u and sorting on size rather than time with -s . The -i flag takes the list of filenames from standard input instead of recursing with find . That way, if you already had a list of filenames, you could feed them to lst for sorting.

The program is shown in Example 9.7 .

Example 9.7: lst

#!/usr/bin/perl # lst - list sorted directory contents (depth first)  use Getopt::Std; use File::Find; use File::stat; use User::pwent; use User::grent;  getopts('lusrcmi')    or die <<DEATH; Usage: $0 [-mucsril] [dirs ...]  or    $0 -i [-mucsrl] < filelist  Input format:     -i  read pathnames from stdin Output format:     -l  long listing Sort on:     -m  use mtime (modify time) [DEFAULT]     -u  use atime (access time)     -c  use ctime (inode change time)     -s  use size for sorting Ordering:     -r  reverse sort NB: You may only use select one sorting option at a time. DEATH      unless ($opt_i || @ARGV) { @ARGV = ('.') }  if ($opt_c + $opt_u + $opt_s + $opt_m > 1) {     die "can only sort on one time or size"; }  $IDX = 'mtime'; $IDX = 'atime' if $opt_u; $IDX = 'ctime' if $opt_c; $IDX = 'size'  if $opt_s;  $TIME_IDX = $opt_s ? 'mtime' : $IDX;  *name = *File::Find::name;  # forcibly import that variable  # the $opt_i flag tricks wanted into taking # its filenames from ARGV instead of being # called from find.  if ($opt_i) {      *name = *_;  # $name now alias for $_      while (<>) { chomp; &wanted; }   # ok, not stdin really }  else {     find(\&wanted, @ARGV); }  # sort the files by their cached times, youngest first @skeys = sort { $time{$b} <=> $time{$a} } keys %time;  # but flip the order if -r was supplied on command line @skeys = reverse @skeys if $opt_r;  for (@skeys) {     unless ($opt_l) {  # emulate ls -l, except for permissions         print "$_\n";         next;     }     $now = localtime $stat{$_}->$TIME_IDX();     printf "%6d %04o %6d %8s %8s %8d %s %s\n",         $stat{$_}->ino(),         $stat{$_}->mode() & 07777,         $stat{$_}->nlink(),         user($stat{$_}->uid()),         group($stat{$_}->gid()),         $stat{$_}->size(),         $now, $_; }  # get stat info on the file, saving the desired # sort criterion (mtime, atime, ctime, or size) # in the %time hash indexed by filename. # if they want a long list, we have to save the # entire stat object in %stat.  yes, this is a # hash of objects sub wanted {     my $sb = stat($_);  # XXX: should be stat or lstat?     return unless $sb;     $time{$name} = $sb->$IDX();  # indirect method call     $stat{$name} = $sb if $opt_l; }  # cache user number to name conversions sub user {     my $uid = shift;     $user{$uid} = getpwuid($uid)->name || "#$uid"         unless defined $user{$uid};     return $user{$uid}; }  # cache group number to name conversions sub group {     my $gid = shift;     $group{$gid} = getgrgid($gid)->name || "#$gid"         unless defined $group{$gid};     return $group{$gid};







 }


Previous: 9.11. Program: symirror Perl Cookbook Next: 10. Subroutines
9.11. Program: symirror Book Index 10. Subroutines

Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.