Renaming files with zmv

Sometimes you want to rename a bunch of files. For example, maybe you want to rename all the .htm files in the directory to .html. Previously I’d give a shell command like this:

for f in *.htm; do
    mv $f $(basename $f .htm).html
done

It works, but it’s cumbersome. There are better tools available. For example, Perl comes with rename, which lets you do this:

rename 's/\.htm$/.html/' *.htm

Another tool, and the one I’ve been using lately, is zmv, which is a part of Zsh. The .htm renaming goes like this:

zmv '(*).htm' '$1.html'

As a more advanced example, recently I wanted to rename all the subdirectories of a directory to uppercase. This was inside a git repo, so I needed to use git mv instead of plain mv. Here’s how I did it:

zmv -Q -i -p 'git' -o 'mv' '(*)(/)' '${(U)1}'
  • -Q turns on bare glob qualifiers. This is required for (/), which makes * match only directories.
  • -i enables interactive mode, as I wanted to manually confirm each renaming.
  • -p specfifies the program and -o the arguments for it.

To use zmv, you need to load it with autoload -U zmv. See man zshcontrib for documentation. I also highly recommend skimming the Zsh manual on expansion (man zshexpn) – it’s a treasure trove that keeps giving.


Comments or questions? Tweet to me or send me an e-mail.