1
0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-11-18 21:14:11 +01:00

+ Added -W to auto-convert wildcards in both the find and replace strings.

+ Fixed the usage message to output the '$' args and '\' characters (they
  were getting eaten).
This commit is contained in:
Wayne Davison 2002-03-30 19:30:11 +00:00
parent 94f73ed646
commit 8224baf73c

@ -13,9 +13,14 @@
# path. Note that you need to write it like this; you can't get away with
# '(**/*).txt'.
# zmv -w '**/*.txt' '$1$2.lis'
# This is the lazy version of the one above; zsh picks out the patterns
# for you. The catch here is that you don't need the / in the replacement
# pattern. (It's not really a catch, since $1 can be empty.)
# noglob zmv -W **/*.txt **/*.lis
# These are the lazy version of the one above; with -w, zsh inserts the
# parentheses for you in the search pattern, and with -W it also inserts
# the numbered variables for you in the replacement pattern. The catch
# in the first version is that you don't need the / in the replacement
# pattern. (It's not really a catch, since $1 can be empty.) Note that
# -W actually inserts ${1}, ${2}, etc., so it works even if you put a
# number after a wildcard (such as zmv -W '*1.txt' '*2.txt').
# zmv -C '**/(*).txt' ~/save/'$1'.lis
# Copy, instead of move, all .txt files in subdirectories to .lis files
# in the single directory `~/save'. Note that the ~ was not quoted.
@ -91,6 +96,8 @@
# where <oldname> and <newname> are filenames generated.
# -w Pick out wildcard parts of the pattern, as described above, and
# implicitly add parentheses for referring to them.
# -W Just like -w, with the addition of turning wildcards in the
# replacement pattern into sequential ${1} .. ${N} references.
# -C
# -L
# -M Force cp, ln or mv, respectively, regardless of the name of the
@ -116,12 +123,12 @@ setopt extendedglob
local f g args match mbegin mend files action myname tmpf opt exec
local opt_f opt_i opt_n opt_q opt_Q opt_s opt_M opt_C opt_L
local opt_o opt_p opt_v opt_w MATCH MBEGIN MEND
local opt_o opt_p opt_v opt_w opt_W MATCH MBEGIN MEND
local pat repl errstr fpat hasglobqual opat
typeset -A from to
integer stat
while getopts ":o:p:MCLfinqQsvw" opt; do
while getopts ":o:p:MCLfinqQsvwW" opt; do
if [[ $opt = "?" ]]; then
print -P "%N: unrecognized option: -$OPTARG" >&2
return 1
@ -138,12 +145,18 @@ done
if (( $# != 2 )); then
print -P "Usage:
%N oldpattern newpattern
%N [OPTIONS] oldpattern newpattern
where oldpattern contains parenthesis surrounding patterns which will
be replaced in turn by $1, $2, ... in newpattern. For example,
%N '(*).lis' '\$1.txt'
be replaced in turn by \$1, \$2, ... in newpattern. For example,
%N '(*).lis' '\\\\\$1.txt'
renames 'foo.lis' to 'foo.txt', 'my.old.stuff.lis' to 'my.old.stuff.txt',
and so on." >&2
and so on. Something simpler (for basic commands) is the -W option:
%N -W '*.lis' '*.txt'
This does the same thing as the first command, but with automatic conversion
of the wildcards into the appropriate syntax. If you combine this with
noglob, you don't even need to quote the arguments. For example,
alias mmv='noglob zmv -W'
mmv *.c.orig orig/*.c" >&2
return 1
fi
@ -173,19 +186,32 @@ if [[ -n $opt_s && $action != ln ]]; then
return 1
fi
if [[ -n $opt_w ]]; then
if [[ -n $opt_w || -n $opt_W ]]; then
# Parenthesise all wildcards.
local newpat
local tmp find
integer cnt=0
# Well, this seems to work.
# The tricky bit is getting all forms of [...] correct, but as long
# as we require inactive bits to be backslashed its not so bad.
newpat="${pat//\
(#m)(\*\*#\/|[*?]|\<[0-9]#-[0-9]#\>|\[(\[:[a-z]##:\]|\\\[|\\\]|[^\[\]]##)##\])\##\
/($MATCH)}"
if [[ $newpat = $pat ]]; then
print -P "%N: warning: no wildcards were found" >&2
find='(#m)(\*\*#[/]|[*?]|\<[0-9]#-[0-9]#\>|\[(\[:[a-z]##:\]|\\\[|\\\]|[^\[\]]##)##\])\##'
tmp="${pat//${~find}/$[++cnt]}"
if [[ $cnt = 0 ]]; then
print -P "%N: warning: no wildcards were found in search pattern" >&2
else
pat=$newpat
pat="${pat//${~find}/($MATCH)}"
fi
if [[ -n $opt_W ]]; then
# Turn wildcards into ${1} .. ${N} references.
local open='${' close='}'
integer N=0
repl="${repl//${~find}/$open$[++N]$close}"
if [[ $N != $cnt ]]; then
print -P "%N: error: number of wildcards in each pattern must match" >&2
return 1
fi
if [[ $N = 0 ]]; then
print -P "%N: warning: no wildcards were found in replacement pattern" >&2
fi
fi
fi