#!/usr/bin/perl -w
# $Id: touch-dirs,v 1.6 2015/05/01 08:04:02 tom Exp $
# Traverse the given directory tree(s), and set the modification time on each
# directory to match the newest file in the directory (or its subdirectories).
# Ignore symbolic links.
#
# This is used to make "identical" tarballs from a given directory at different
# times, using "archive -t".

 
use strict;
 
use Getopt::Std;
use File::stat;
 
use vars qw($opt_n $opt_v);
 
sub touch_dirs($) {
    my $pathname = $_[0];
    my $newest   = 0;
    my $modtime;
    my $lnktime = 0;
    my @list;
    my $sb;
    my $n;
    my $dh;
 
    printf "** %s\n"$pathname if $opt_v;
 
    opendir( DIR, $pathname ) || die "can't opendir $pathname$!";
    @list = sort readdir(DIR);
    closedir DIR;
 
    for $n ( 0 .. $#list ) {
        next if ( $list[$neq "." );
        next if ( $list[$neq ".." );
 
        my $item = $pathname . "/" . $list[$n];
 
        $sb = lstat $item;
        if ( $sb->mode & 020000 ) {    # symbolic link
            my $sb2 = stat $item;
            if ($sb2) {
                printf "...links %s\n"scalar localtime $sb2->mtime if $opt_v;
                $lnktime = $sb2->mtime if ( $lnktime < $sb2->mtime );
            }
            next;
        }
 
        printf "%d:%s\n"$n$item if $opt_v;
        $modtime = $sb->mtime;
        if ( $sb->mode & 040000 ) {
            $modtime = &touch_dirs($item);
        }
        if ( $modtime > $newest ) {
            printf "...newer %s\n"scalar localtime $modtime if $opt_v;
            $newest = $modtime;
        }
    }
 
    $newest = $lnktime if ( $newest == 0 );
 
    if ( $newest ne 0 ) {
        if ($opt_n) {
            $sb = lstat $pathname;
            if ( $sb->mtime ne $newest ) {
                printf "...touch %s %s\n"scalar localtime $newest$pathname;
            }
        }
        else {
            utime $newest$newest$pathname;
        }
    }
    return $newest;
}
 
&getopts('nv');
 
if ( $#ARGV >= 0 ) {
    while ( $#ARGV >= 0 ) {
        &touch_dirsshift @ARGV );
    }
}
else {
    &touch_dirs(".");
}