#!/usr/bin/perl $rcpcmd = 'rcp'; $scpcmd = 'scp'; $pwdcmd = '/bin/pwd'; @rmcmd = ('rm'); @rmrcmd = ('rm', '-r'); $tagcmd = 'tag'; # scph - remote copy files to other (home) directories, keeping relative paths # Steve Kinzler, kinzler@cs.indiana.edu, Apr 00/Jun 03 # http://www.cs.indiana.edu/~kinzler/home.html#homedir require 5.000; use Getopt::Std; $dcpcmd = ($0 =~ m:scph[^/]*$:) ? $scpcmd : $rcpcmd; $usage = "usage: $0 [ -S | -s ] [ -d dir ] [ -nqxXprt ] file ... [ host | == host ... ] -S use rcp, default \$RCPHRCP or $dcpcmd -s use scp, default \$RCPHRCP or $dcpcmd -d use the given reference directory for paths, default \$HOME -n no execute, just print commands -q quiet mode, don't print commands -x remove local files after copying them okay -X remove local directories and files after copying them okay, requires -r -p, -r passed to rcp/scp -t don't expand tag file specifiers with `$tagcmd` The given files are copied to the given hosts to the same location relative to the user's home directory, or relative to the path given with a -d option. All files must be hard under the reference directory. If a file argument does not exist and is an alphanumeric (plus '-') string and the -t option is not given and a tag expansion command is configured, then the argument will be taken as a tag for expansion into a file with the command.\n"; getopts('hSsd:nqxXprt') or die $usage; die $usage if $opt_h || $#ARGV < 1 || $opt_X && ! $opt_r; $i = -1; foreach (@ARGV) { $i++; last if $_ eq '==' } @hosts = splice(@ARGV, $i); shift @hosts if $hosts[0] eq '=='; die $usage unless @ARGV && @hosts; ############################################################################### chop($cwd = `$pwdcmd`); die "$0: $pwdcmd error ($!)\n" if $? || $cwd eq ''; $cmd = ($opt_s) ? $scpcmd : ($opt_S) ? $rcpcmd : ($ENV{'RCPHRCP'}) ? $ENV{'RCPHRCP'} : $dcpcmd; $dir = $opt_d || $ENV{'HOME'} or die "$0: cannot find HOME\n"; -d $dir or die "$0: invalid reference directory ($dir)\n"; $dira = &absdir("$dir/.") or exit 1; $exit = 0; %err = (); $badhost = 0; foreach (@ARGV) { chop($_ = `$tagcmd $_` || "$_\n") if ! $opt_t && ! -r && $tagcmd && /^[-\w]+$/; warn("$0: skipping file $_, no such readable file or directory\n"), $exit = 1, next unless -r; $_dir = &absdir($_); warn("$0: file ($_ in $_dir) not hard under the reference directory " . "($dira)\n"), next unless $_dir =~ m:^\Q$dira\E(/|$):; if ($opt_d) { $_dir =~ s:^\Q$dira\E:$dir: } else { $_dir =~ s:^\Q$dira\E/?:: } push(@{$files{$_dir}}, $_); } while (@hosts) { $host = shift @hosts; warn("$0: skipping host $host, invalid\n"), $exit = $badhost = 1, next unless $host =~ /^[-\w.]+$/; foreach (sort keys %files) { &run($cmd, ($opt_p) ? '-p' : (), ($opt_r) ? '-r' : (), @{$files{$_}}, "$host:$_"); next if @hosts || $err{$_} || $badhost; &run(($opt_x) ? @rmcmd : ($opt_X) ? @rmrcmd : next, @{$files{$_}}); } } exit 1 if $exit; ############################################################################### sub run { print(($opt_n) ? ': ' : '', join(' ', @_), "\n") unless $opt_q; eval { system(@_) } unless $opt_n; $exit = $err{$_} = $? if $?; } sub absdir { local($_) = @_; s:/+:/:g; s:^/$:/.:; s:/$::; $_ = (($cwd =~ m:^/+$:) ? '' : $cwd) . "/$_" unless m:^/:; s:[^/]*$::; s:':'\\'':g; chop($_ = `cd '$_'; $pwdcmd`); warn("$0: $pwdcmd error ($!)\n"), return '' if $? || $_ eq ''; $_; }