1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-27 16:50:58 +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

View file

@ -13,9 +13,14 @@
# path. Note that you need to write it like this; you can't get away with # path. Note that you need to write it like this; you can't get away with
# '(**/*).txt'. # '(**/*).txt'.
# zmv -w '**/*.txt' '$1$2.lis' # zmv -w '**/*.txt' '$1$2.lis'
# This is the lazy version of the one above; zsh picks out the patterns # noglob zmv -W **/*.txt **/*.lis
# for you. The catch here is that you don't need the / in the replacement # These are the lazy version of the one above; with -w, zsh inserts the
# pattern. (It's not really a catch, since $1 can be empty.) # 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 # zmv -C '**/(*).txt' ~/save/'$1'.lis
# Copy, instead of move, all .txt files in subdirectories to .lis files # Copy, instead of move, all .txt files in subdirectories to .lis files
# in the single directory `~/save'. Note that the ~ was not quoted. # in the single directory `~/save'. Note that the ~ was not quoted.
@ -91,6 +96,8 @@
# where <oldname> and <newname> are filenames generated. # where <oldname> and <newname> are filenames generated.
# -w Pick out wildcard parts of the pattern, as described above, and # -w Pick out wildcard parts of the pattern, as described above, and
# implicitly add parentheses for referring to them. # 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 # -C
# -L # -L
# -M Force cp, ln or mv, respectively, regardless of the name of the # -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 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_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 local pat repl errstr fpat hasglobqual opat
typeset -A from to typeset -A from to
integer stat integer stat
while getopts ":o:p:MCLfinqQsvw" opt; do while getopts ":o:p:MCLfinqQsvwW" opt; do
if [[ $opt = "?" ]]; then if [[ $opt = "?" ]]; then
print -P "%N: unrecognized option: -$OPTARG" >&2 print -P "%N: unrecognized option: -$OPTARG" >&2
return 1 return 1
@ -138,12 +145,18 @@ done
if (( $# != 2 )); then if (( $# != 2 )); then
print -P "Usage: print -P "Usage:
%N oldpattern newpattern %N [OPTIONS] oldpattern newpattern
where oldpattern contains parenthesis surrounding patterns which will where oldpattern contains parenthesis surrounding patterns which will
be replaced in turn by $1, $2, ... in newpattern. For example, be replaced in turn by \$1, \$2, ... in newpattern. For example,
%N '(*).lis' '\$1.txt' %N '(*).lis' '\\\\\$1.txt'
renames 'foo.lis' to 'foo.txt', 'my.old.stuff.lis' to 'my.old.stuff.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 return 1
fi fi
@ -173,19 +186,32 @@ if [[ -n $opt_s && $action != ln ]]; then
return 1 return 1
fi fi
if [[ -n $opt_w ]]; then if [[ -n $opt_w || -n $opt_W ]]; then
# Parenthesise all wildcards. # Parenthesise all wildcards.
local newpat local tmp find
integer cnt=0
# Well, this seems to work. # Well, this seems to work.
# The tricky bit is getting all forms of [...] correct, but as long # The tricky bit is getting all forms of [...] correct, but as long
# as we require inactive bits to be backslashed its not so bad. # as we require inactive bits to be backslashed its not so bad.
newpat="${pat//\ find='(#m)(\*\*#[/]|[*?]|\<[0-9]#-[0-9]#\>|\[(\[:[a-z]##:\]|\\\[|\\\]|[^\[\]]##)##\])\##'
(#m)(\*\*#\/|[*?]|\<[0-9]#-[0-9]#\>|\[(\[:[a-z]##:\]|\\\[|\\\]|[^\[\]]##)##\])\##\ tmp="${pat//${~find}/$[++cnt]}"
/($MATCH)}" if [[ $cnt = 0 ]]; then
if [[ $newpat = $pat ]]; then print -P "%N: warning: no wildcards were found in search pattern" >&2
print -P "%N: warning: no wildcards were found" >&2
else 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
fi fi