#! /usr/local/bin/perl
# grind-over-tree -- run a command over every file in a directory tree
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1995-11-09
# Public domain.

# $Id: grind-over-tree.pl,v 1.0 1995/11/09 17:27:37 friedman Exp $

# Commentary:
# Code:

$stat = &grind_over_tree ($ARGV[0], 'html_p', 'run_command');
exit (! $stat);

sub html_p
{
  local ($file) = @_;

  if ($file =~ /\.html?$/)
    {
      return 1;
    }
  return 0;
}

sub run_command
{
  &invoke ($ARGV[1], @_);
}

# The rest are utility routines

sub grind_over_tree
{
  local ($dir, $predicate, $action) = @_;
  local ($noerrs) = 1;
  local (@files);

  if (! opendir (DIRHNDL, $dir))
    {
      printf (STDERR "opendir: $dir: $!.\n");
      return 0;
    }

  @files = grep (!/^\.\.?$/, readdir (DIRHNDL));
  close (DIRHNDL);

  foreach $ent (@files)
    {
      local ($file) = "$dir/$ent";

      if (-d $file)
        {
          if (! &grind_over_tree ($file, $predicate, $action))
            {
              $noerrs = 0;
            }
        }
      else
        {
          if (&$predicate ($file))
            {
              if (! &$action ($file))
                {
                  $noerrs = 0;
                }
            }
        }
    }
  return $noerrs;
}

# This function does its own fork+exec, to avoid the overhead (and
# potential argument rescanning problems) of invoking a shell with
# the `system' function.
sub invoke
{
  local ($stat) = fork;

  if ($stat == 0)
    {
      exec (@_);
    }
  elsif ($stat == -1)
    {
      printf (STDERR "fork: $!.\n");
      return 0;
    }
  else
    {
      wait;
    }
  return 1;
}

# eof
