\cfg{man-identity}{multi}{1}{2004-11-20}{Simon Tatham}{Simon Tatham} \define{dash} \u2013{-} \title Man page for \cw{multi} \U NAME \cw{multi} \dash bulk file rename/copy utility using Perl regexps \U SYNOPSIS \c multi [ -n | -q ] [ -r ] cmd perlfragment file [file...] \e bbbbb bb bb bb iii iiiiiiiiiiii iiii iiii \c multi [ -n | -q ] [ -r ] - cmd cmd - perlfragment file [file...] \e bbbbb bb bb bb iii iii iiiiiiiiiiii iiii iiii \U DESCRIPTION \cw{multi} is a utility which allows you to invoke a command (typically, but not always, \cw{mv} or \cw{cp}) on a lot of files in a complicated way. The command-line arguments to \cw{multi} include a command, a set of filenames, and a fragment of Perl. For each of the filenames, \cw{multi} will use the fragment of Perl to transform the filename into a new filename, and will then invoke the given command, passing the old and new filenames as arguments. \cw{multi} is most often useful as a bulk rename or copy utility, by passing \cw{mv} or \cw{cp} as the command. However, it can have more complex uses as well; see the examples below. \U ARGUMENTS \dt \e{cmd} \dd Provides the command to which pairs of filenames will eventually be passed. If this is just one word (typically \c{cp} or \c{mv}), you can simply supply that word on the command line. \lcont{ A multiple-word command (such as \c{ln -s} or \c{svn mv}) can be used if you place it between two arguments containing only minus signs. } \dt \e{perlfragment} \dd This fragment of Perl will be run for each file name you supply. The file name will be passed in in the special Perl variable \cw{$_}, and the altered file name should be passed out in \cw{$_} as well. (Therefore, the simplest kind of Perl fragment you could use is a single \cw{s///} substitution command.) \lcont{ All the Perl variable names used internally by \cw{multi} itself begin with two underscore characters. Therefore, your Perl fragment can safely define its own variables (provided they do not begin with two underscores), without worrying about upsetting the functioning of \cw{multi}. } \dt \e{files} \dd After the Perl fragment, \cw{multi} expects a list of file names to be transformed. Typically these will be generated by typing one or more wildcard expressions on the shell command line. \U OPTIONS By default, \cw{multi} will print every command it executes on standard output, so that you can see what it has just done (in case it turns out to be wrong!). Bourne-shell-style quoting is provided, so that copying the output of \cw{multi} and pasting it into a shell script or on to a shell command line should work correctly. \dt \cw{-n} \dd Do not actually execute the commands. Instead, \e{only} print them on standard output as they would be executed. (Useful for a dry run to make sure your Perl does what you meant it to do. When you've got it right, take off the \cw{-n} option and let it run for real.) \dt \cw{-q} \dd \e{Only} execute the commands, without printing them. (Useful for running within a larger script.) By default, the two arguments passed to each invocation of the subcommand are the original filename and the transformed filename, in that order. \dt \cw{-r} \dd Reverse the order of arguments to the subcommand, so that it receives the transformed file name \e{before} the original one. \U EXAMPLES The simplest use of \cw{multi} is to rename a large number of files. Suppose, for example, you have a lot of text files with \cw{.txt} extensions, and you prefer to use \cw{.text} extensions: \c $ multi mv 's/.txt$/.text/' *.txt \e bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \c mv bar.txt bar.text \c mv baz.txt baz.text \c mv foo.txt foo.text If you wanted to copy the files rather than moving them, the command becomes \c $ multi cp 's/.txt$/.text/' *.txt \e bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \c cp bar.txt bar.text \c cp baz.txt baz.text \c cp foo.txt foo.text If you wanted to create symbolic links, you now need the command \cw{ln -s}, which is composed of two words. So you need to tell \cw{multi} where the command words stop and the Perl begins, using two single-dash arguments: \c $ multi - ln -s - 's/.txt$/.text/' *.txt \e bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \c ln -s bar.txt bar.text \c ln -s baz.txt baz.text \c ln -s foo.txt foo.text Note that simply quoting the two-word command would not have worked, because \cw{multi} would have assumed you genuinely meant a one-word command which had a space in the middle... \c $ multi "ln -s" 's/.txt$/.text/' *.txt \e bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \c 'ln -s' bar.txt bar.text \c 'ln -s' baz.txt baz.text \c 'ln -s' foo.txt foo.text ... which was almost certainly not what you wanted! The version control utility \e{Subversion} has a subcommand for moving files around within your working directory. However, it does not support wildcards, because \cw{svn mv} expects to see \e{precisely} two arguments. So if you want to move a whole load of files into a subdirectory, a command such as \cw{svn mv win*.c windows} will not work. \cw{multi} comes to the rescue: \c $ multi - svn mv - 's:^:windows/:' win*.c \e bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \c svn mv winmain.c windows/winmain.c \c svn mv winprint.c windows/winprint.c \c svn mv winutils.c windows/winutils.c Of course, your Perl fragment can be more complex than just a \cw{s///} command. Here's a means of tidying up after extracting an MS-DOS zip file containing all filenames in upper case: \c $ multi mv 'y/A-Z/a-z/' *[A-Z]* \e bbbbbbbbbbbbbbbbbbbbbbbbbbbbb \c mv HEADER.H header.h \c mv MAIN.C main.c \c mv STUFF.C stuff.c Here's an example using \cw{-r}. Suppose you have lots of \c{.wav} sound files, and you want to encode them all into compressed Ogg Vorbis format. The \c{oggenc} command expects its destination file name as an argument to the \c{-o} parameter, so it's most convenient to put that \e{before} the input file name: \c $ multi -r - oggenc -o - 's/.wav$/.ogg/' *.wav \e bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \c oggenc -o bar.ogg bar.wav \c oggenc -o baz.ogg baz.wav \c oggenc -o foo.ogg foo.wav Finally, here's a general technique for going beyond the limits of \cw{multi}, in the case where you need to do something more ambitious with your two file names. Suppose you want to use one file name as the target of a shell redirection operator, for example. \c $ multi - sh -c 'grep foo $0 > $1' - 's/.txt$/.grepped/' *.txt \e bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \c sh -c 'grep foo $0 > $1' bar.txt bar.grepped \c sh -c 'grep foo $0 > $1' baz.txt baz.grepped \c sh -c 'grep foo $0 > $1' foo.txt foo.grepped As each of these commands will be executed, the (explicitly invoked) shell will substitute the two filename arguments in place of \cw{$0} and \cw{$1}, so that the \e{effect} will be that of running a set of commands like \c grep foo bar.txt > bar.grepped \c grep foo baz.txt > baz.grepped \c grep foo foo.txt > foo.grepped \U ACKNOWLEDGEMENTS The O'Reilly book \q{Programming Perl} includes a simple example script which contains the core idea of this program. It takes a single Perl argument followed by filenames, and invokes Perl's internal \cw{rename} function. \cw{multi} is a complete rewrite of this basic idea, supplying more options and configurability. \U LICENCE \cw{multi} is free software, distributed under the MIT licence. Type \cw{multi --licence} to see the full licence text. \versionid $Id$