#!/usr/pkg/bin/perl

=begin metadata

Name: apply
Description: run a command many times with different arguments
Author: Abigail, perlpowertools@abigail.be
License: perl

=end metadata

=cut


use strict;

use File::Basename qw(basename);
use List::Util qw(max);

use constant EX_SUCCESS => 0;
use constant EX_FAILURE => 1;

my $Program = basename($0);
my ($VERSION) = '1.5';

my $argc  = 1;
my $debug = 0;
my $magic = '%';

while (@ARGV) {
    if ($ARGV[0] !~ m/\A\-/) {
        last;
    }
    if ($ARGV[0] eq '--') {
        shift;
        last;
    }

    if ($ARGV[0] =~ s/\A\-a//) {
        $magic = $ARGV[0];
        unless (length $magic) {
            shift;
            $magic = $ARGV[0];
        }
        unless (length $magic) {
            warn "$Program: option -a requires an argument\n";
            usage();
        }
        if (length($magic) > 1) {
            warn "$Program: invalid magic specification\n";
            usage();
        }
    }
    elsif ($ARGV[0] =~ m/\A\-(\d+)\Z/) {
        $argc = $1;
    }
    elsif ($ARGV[0] eq '-d') {
        $debug = 1;
    }
    else {
        warn "$Program: invalid option: $ARGV[0]\n";
        usage();  # usage will exit
    }
    shift;
}

my $command = shift;
usage() unless @ARGV;

# Scan $command for ``%d''.
my @thingies = $command =~ /${magic}(\d+)/g;
$argc = max(@thingies) if @thingies;

# Now, apply the command till we run out.
my $err = EX_SUCCESS;
while (@ARGV && @ARGV >= $argc) {
    if (@thingies) {
       (my $new_command = $command) =~ s/${magic}(\d+)/$ARGV [$1 - 1]/ge;
        run_cmd($new_command); # Reinterpreted by the shell!
        splice @ARGV, 0, $argc;
    }
    else {
        if ($argc) {
            run_cmd($command, splice(@ARGV, 0, $argc));
        }
        else {
            shift;
            run_cmd($command);
        }
    }
}
if (@ARGV) {
    warn "$Program: unexpected number of arguments\n";
    $err = EX_FAILURE;
}
exit $err;

sub run_cmd {
    my $cmd = shift;
    if ($debug) {
        print join(' ', 'exec', $cmd, @_), "\n";
        return;
    }
    my $status = system $cmd, @_;
    if ($status != 0) {
        if ($status == -1) {
            warn "$Program: command failed: $!\n";
        }
        $err = EX_FAILURE;
    }
}

sub usage {
    warn "usage: $Program [-a c] [-d] [-#] command argument [argument ...]\n";
    exit EX_FAILURE;
}

__END__

=pod

=head1 NAME

apply - Run a command many times with different arguments

=head1 SYNOPSIS

apply [-a B<c>] [-d] [-#] command argument [argument ...]

=head1 DESCRIPTION

I<apply> runs the given command multiple times, with different arguments.
Without arguments, I<command> is run once for each argument. If the
command contains strings of the form B<%d+>, the d'th next unused argument
will be substituted.

=head2 OPTIONS

I<apply> accepts the following options:

=over 4

=item -a B<c>

Use the character B<c> instead of B<%> for interpolation of arguments.

=item -d

Print each constructed command but do not execute it.

=item -#

If an option of the form I<-#> is given, with I<#> a number, I<apply>
uses that many arguments for each call of I<command>. If I<-0> is given
as an option, I<command> is called without arguments, and it is called
as many times as there are arguments following I<command> on the command
line.

This option is ignored if I<command> has magic B<%d+> sequences.

=back

=head1 ENVIRONMENT

The working of I<apply> is not influenced by any environment variables.

=head1 CAVEATS

When I<command> has magic B<%d+> sequences, the string after interpolation
of the arguments is handed to a shell for interpretation of meta characters.
This shell is determined by Perl, during its building phase, and is typically
C</bin/sh -c> on Unix platforms.

=head1 BUGS

I<apply> does not honor the users C<$SHELL> environment variable.

=head1 REVISION HISTORY

    $Log: apply,v $
    Revision 1.2  2004/08/05 14:17:43  cwest
    cleanup, new version number on website

    Revision 1.1  2004/07/23 20:09:59  cwest
    initial import

    Revision 1.1  1999/02/27 03:36:18  abigail
    Initial revision

=head1 AUTHOR

The Perl implementation of I<apply> was written by Abigail, I<perlpowertools@abigail.be>.

=head1 COPYRIGHT and LICENSE

This program is copyright by Abigail 1999.

This program is free and open software. You may use, copy, modify, distribute
and sell this program (and any modified variants) in any way you wish,
provided you do not restrict others to do the same.

=cut

