Missed out a highlight.
[sgt/utils] / multi / multi
1 #!/usr/bin/env perl
2
3 # Perform multiple moves/copies.
4
5 # Usage: multi mv 's/$/.old/' *.c
6 # multi cp 's:/tmp/(.*):$1:' *
7 # multi - svn mv - 's/foo/bar/' *foo*
8 #
9 # Options: -n don't actually do anything, just print what it would do
10 # -r reverse the arguments to each command
11 # -q don't print the commands as they are executed
12
13 # Note that all variables in this script begin with a double
14 # underscore. This is because the <action> parameter is a piece of
15 # user-supplied Perl, which might perfectly legitimately want to
16 # define and use its own variables in the course of doing a complex
17 # transformation on file names. Thus, I arrange that all _my_
18 # variables stay as far out of its likely namespace as they can.
19
20 $__quiet = $__donothing = $__reverse = 0;
21
22 while ($ARGV[0] =~ /^-(.+)$/) {
23 shift @ARGV;
24 $__quiet = 1, next if $1 eq "q";
25 $__quiet = 0, $__donothing = 1, next if $1 eq "n";
26 $__reverse = 1, next if $1 eq "r";
27 }
28
29 die "usage: multi <cmd> <action> <files>\n" .
30 " e.g. multi mv 'tr/A-Z/a-z/' *\n" if $#ARGV < 2;
31 " also: multi - <multiple-word-cmd> - <action> <files>\n" .
32 " or multi - svn mv - 'tr/A-Z/a-z/' *\n" if $#ARGV < 2;
33
34 @__cmd = ();
35 if ($ARGV[0] eq "-") {
36 shift @ARGV;
37 while (defined $ARGV[0] and $ARGV[0] ne "-") {
38 push @__cmd, shift @ARGV;
39 }
40 if (!defined $ARGV[0]) {
41 die "multi: no terminating - in multiple-word command mode\n";
42 }
43 shift @ARGV; # eat trailing -
44 } else {
45 $__cmd[0] = shift @ARGV;
46 }
47 $__action = shift @ARGV;
48
49 while (@ARGV) {
50 $_ = $__origfile = shift @ARGV;
51 eval $__action;
52 $__newfile = $_;
53 ($__origfile, $__newfile) = ($__newfile, $__origfile) if $__reverse;
54 &pcmd(@__cmd, $__origfile, $__newfile) if !$__quiet;
55 system @__cmd, $__origfile, $__newfile if !$__donothing;
56 }
57
58 sub pcmd {
59 my (@words) = @_;
60 printf "%s\n", join " ", map { &fmt($_) } @words;
61 }
62
63 sub fmt {
64 local ($_) = @_;
65 if (/[ !"#$&'()*;<>?\\`|~]/) {
66 s/'/'\\''/g;
67 "'$_'";
68 } else {
69 $_;
70 }
71 }