29efe1b9 |
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 | |
da0f8522 |
20 | $usage = |
c52f9fb9 |
21 | "usage: multi [flags] <cmd> <action> <files>\n" . |
da0f8522 |
22 | " e.g. multi mv 'tr/A-Z/a-z/' *\n" . |
c52f9fb9 |
23 | " or: multi [flags] - <multiple-word-cmd> - <action> <files>\n" . |
da0f8522 |
24 | " e.g. multi - svn mv - 'tr/A-Z/a-z/' *\n" . |
c52f9fb9 |
25 | "where: -n print commands, but do not execute\n" . |
26 | "where: -q execute commands, but do not print\n" . |
27 | "where: -r reverse order of filenames passed to commands\n" . |
da0f8522 |
28 | " also: multi --version report version number\n" . |
29 | " multi --help display this help text\n" . |
30 | " multi --licence display (MIT) licence text\n"; |
31 | |
32 | $licence = |
33 | "multi is copyright 1999-2004 Simon Tatham.\n" . |
34 | "\n" . |
35 | "Permission is hereby granted, free of charge, to any person\n" . |
36 | "obtaining a copy of this software and associated documentation files\n" . |
37 | "(the \"Software\"), to deal in the Software without restriction,\n" . |
38 | "including without limitation the rights to use, copy, modify, merge,\n" . |
39 | "publish, distribute, sublicense, and/or sell copies of the Software,\n" . |
40 | "and to permit persons to whom the Software is furnished to do so,\n" . |
41 | "subject to the following conditions:\n" . |
42 | "\n" . |
43 | "The above copyright notice and this permission notice shall be\n" . |
44 | "included in all copies or substantial portions of the Software.\n" . |
45 | "\n" . |
46 | "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n" . |
47 | "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n" . |
48 | "MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n" . |
49 | "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n" . |
50 | "BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n" . |
51 | "ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n" . |
52 | "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n" . |
53 | "SOFTWARE.\n"; |
54 | |
29efe1b9 |
55 | $__quiet = $__donothing = $__reverse = 0; |
56 | |
57 | while ($ARGV[0] =~ /^-(.+)$/) { |
58 | shift @ARGV; |
59 | $__quiet = 1, next if $1 eq "q"; |
60 | $__quiet = 0, $__donothing = 1, next if $1 eq "n"; |
61 | $__reverse = 1, next if $1 eq "r"; |
da0f8522 |
62 | if ($1 eq "-help") { |
63 | print STDERR $usage; |
64 | exit 0; |
65 | } elsif ($1 eq "-version") { |
66 | if ('$Revision$' =~ /Revision:\s+(\d+)/) { |
67 | print "multi revision $1\n"; |
68 | } else { |
69 | print "multi: unknown revision\n"; |
70 | } |
71 | exit 0; |
72 | } elsif ($1 eq "-licence" or $1 eq "-license") { |
73 | print $licence; |
74 | exit 0; |
75 | } |
29efe1b9 |
76 | } |
77 | |
da0f8522 |
78 | die $usage if $#ARGV < 2; |
29efe1b9 |
79 | |
80 | @__cmd = (); |
81 | if ($ARGV[0] eq "-") { |
82 | shift @ARGV; |
83 | while (defined $ARGV[0] and $ARGV[0] ne "-") { |
84 | push @__cmd, shift @ARGV; |
85 | } |
86 | if (!defined $ARGV[0]) { |
87 | die "multi: no terminating - in multiple-word command mode\n"; |
88 | } |
89 | shift @ARGV; # eat trailing - |
90 | } else { |
91 | $__cmd[0] = shift @ARGV; |
92 | } |
93 | $__action = shift @ARGV; |
94 | |
95 | while (@ARGV) { |
96 | $_ = $__origfile = shift @ARGV; |
97 | eval $__action; |
98 | $__newfile = $_; |
99 | ($__origfile, $__newfile) = ($__newfile, $__origfile) if $__reverse; |
100 | &pcmd(@__cmd, $__origfile, $__newfile) if !$__quiet; |
101 | system @__cmd, $__origfile, $__newfile if !$__donothing; |
102 | } |
103 | |
104 | sub pcmd { |
105 | my (@words) = @_; |
106 | printf "%s\n", join " ", map { &fmt($_) } @words; |
107 | } |
108 | |
109 | sub fmt { |
110 | local ($_) = @_; |
111 | if (/[ !"#$&'()*;<>?\\`|~]/) { |
112 | s/'/'\\''/g; |
113 | "'$_'"; |
114 | } else { |
115 | $_; |
116 | } |
117 | } |