Bulk File & Directory Renamer with Recursion & Regular Expressions

(Version 7)

What is This?

It a simple program for renaming multiple files & directories (a.k.a. folders) from a command line with support for recursion into subdirectories, regular expressions (a.k.a regexps a.k.a. regexs) and a test (dry run) mode.

You may ask why I have made this when, it being such a useful type of program, there have been many many such programs written by others in the past. Well, I am fussy and did not find one that fitted my liking when I started it so I wrote my own and kept adding new features as I needed them.

Although I mainly wrote for M$ Windows 2k (where very few programs support regular expressions), it should run equally well under Linux or Mac OS X under Perl. (Of course one does not really need a special program for this if one is using GNU/Linux/Bash as a one line mess of 'find', '-name', '-type', '-exec', 'sed' & 'mv' can do it but I am too forgetful of syntax & sloppy with typing to risk destroying files attempting that.)

System Requirements

A Perl interpreter (with the 'File::Find' module but that usually comes as standard with Perl anyway).

How to Use It

Basic Usage

To process all files and directories in the current working directory and subdirectories thereof changing any occurrence of the expression <From> to the expression <To>, simply:

perl RecursiveRegexpRename.pl <From> <To>

Depending on how you can installed the program you might be able to discard some of it and less pedantically do:

RecursiveRegexpRename <From> <To>

Non-trivial expressions and expressions containing spaces will probably need to be in (double for Windows) quotation marks so the shell passes them to the program as strings rather than trying to split up or process them it itself.

Options

There are additional options which can be inserted before the two obligatory regular expressions

perl RecursiveRegexpRename.pl <options> <From> <To>

RecursiveRegexpRename <options> <From> <To>

The options are provided in the common Linux short format of single letters each prefixed by '-' and separated from eachother & parameters by spaces. Options that don't require additional parameters can be grouped (e.g. '-ft ' means the same as '-f -t ').

-h
Print a summary of the instructions. (The instruction summary will also be printed if a syntax error is found in the options or if the program is run without parameters.)
-f
Limit the renaming to files only, not directories. (By default it renames both, equivalent to specifying '-fd'.)
-d
Limit the renaming to directories only, not files. (By default it renames both, equivalent to specifying '-fd'.)
-n <Name>
Limit to filenames matching the <name> regular expression.
-m [egimosx]
Apply the given Perl search & replace modifiers. The most useful for file renaming are:
-b <directory>
Process files within <directory> directory instead of the current working directory.
-e
Do not recurse subdirectories.
-t
Test mode. (It does a dry run printing out the changes it would have made but does not does actually make the changes).

Example: Simple Search and Replace in Multiple File & Directory Names

I find this very useful for correcting spelling mistakes that I have duplicated across lots of file & directory names before noticing, for example with holiday photographs where a friend spots that I have consistently misspelt the name of a place across dozens of photographs.

All it needs is (replace the from & to strings to those required):

Windows: RecursiveRegexpRename -m g "\bLund'n Bridj\b" "London Bridge"

Linux: RecursiveRegexpRename -m g '\bLund'n Bridj\b$' 'London Bridge'

You can use it just as it is as a recipe but if you want an explanation, here goes. The '-m g' tells it to replace every occurrence in each file name (so , for example, 'Lund'n Bridj view, Lund'n Bridj.jpg', becomes 'London Bridge view, London Bridge.jpg' not 'London Bridge view, Lund'n Bridj.jpg'). The '\b' marks word boundaries (more generic than spaces, it also includes pronunciation and string ends) to prevent it changing words of which 'Lund'n Bridj' is a substring. One does not really need these complications in this case as substrings are not likely to be problem so one could simply do 'RecursiveRegexpRename "Lund'n Bridj" "London Bridge"' & repeat the command until it makes no further changes.

Example: Bulk Changing of File Name Extensions

I was asked this by a reader who wanted to rename 2 TiB of image files from '*.fil' to '*.tif'. All it needs is:

Windows: RecursiveRegexpRename -f -m i -t "\.fil$" ".tif"

Linux: RecursiveRegexpRename -f -m i -t '\.fil$' '.tif'

The same method (just changing the parameter text appropriately of course) would work for other common ones like changing '*.txt' to '*.csv' ,'*.tiff' to '*.tif', '*.jpeg' to '*.jpg' & '*.pps' to '*.ppt'.

You can use it just as it is as a recipe but if you want an explanation, here goes. The '-f' restricts it to files lest one has any odd directories named ending with '.fil'. The '-m i' tells it to be case insensitive (so '.Tif', '.TIF' etc. also become '.fil' too). The '\' ensures that the following '.' is treated simply as a '.' character in matches rather than a wildcard ('.' is the single character wildcard in Perl regular expressions, i.e. it is the 'joker' that matches any character) to prevent, for example, 'tasks to fulfil' becoming 'tasks to fu.tif'. The '$' matches the end of a string and so as to prevent, for example 'space.filler.fil' becoming 'space.tifler.fil'. All that is essentially paranoia. Provided one does not have any directory names ending '.fil', any file or directory names with '.fil' other than at the end or any names ending with 'fil' that aren't ending '.fil' then a simple plain 'RecursiveRegexpRename ".fil" ".tif"' would work fine.

Example: Bulk Changing of Spaces Representation

A problem with file names is that they are usually supposed to be useful for a human to read and normal English text has spaces but spaces were (unwisely in my opinion) reserved as file name separator characters in early filesystems so bodges like using "Example_file_name" or "ExampleFileName" for "Example file name" became de facto standards. Thesedays the normal Windows, Linux & Mac filesystems can cope with spaces but some people have got used to the bodged styles and prefer them or have to use them because some applications (most notably the WWW) still don't like spaces.

It can be annoying to receive files from different sources named in a mixture of the formats or in a format that is not one's own preference. However one can, to some extent, use this program to convert them in bulk to the way one wants them.

The following table is for Windows use. For Linux use simply replace all the double quotation marks ('"') with single quotation marks (''').

From
Spaces
(Example file name)
Underscores
(Example_file_name)
Camel case
(ExampleFileName)
To Spaces
(Example file name)
RecursiveRegexpRename -m g "_" " " RecursiveRegexpRename -m g "(?<=.)([A-Z])" " \L$1"
Underscores
(Example_file_name)
RecursiveRegexpRename -m g " " "_" RecursiveRegexpRename -m g "(?<=.)([A-Z])" "_\L$1"
Camel case
(ExampleFileName)
RecursiveRegexpRename -m g "(^| +)(\w*)" "\u\L$2" RecursiveRegexpRename -m g "(^|_+)([^_]*)" "\u\L$2"

Note that there is no way such an automated conversion can work perfectly in every case. For example, it cannot tell that 'FreeBbcTvProgram.mpg' should become 'Free BBC TV program.mpg' not 'Free bbc tv program.mpg'. However it can often do the majority of the work.

Avoiding Command Line Problems

One complication of running programs from a command line is that the command line interpreter ('shell') treats some characters specially and replaces them with other things (such as values of settings or unprintable characters) before running the program. Some of these characters are even treated so inside strings. These risky characters are '\' on Linux & '%' on Windows.

There are two solutions in Linux. The simplest is to use single quotation marks (''...'') instead of double quotation marks ('"..."') for the strings. The other is to prefix ('escape') each '\' with another '\'. E.g. instead of

RecursiveRegexpRename -f -m i -t "\.fil$" ".tif"

use

RecursiveRegexpRename -f -m i -t '\.fil$' '.tif'

or

RecursiveRegexpRename -f -m i -t "\\.fil$" ".tif"

In Windows I don't know how to prevent it substituting things beginning with '%' if it recognises them as settings (such as '%TMP%', the path to the system temporary directory). Within batch files supposedly prefixing '%' with '^' works but that did not work when I tested it directly on a command line. Fortunately '%' is rarely used either in Perl regular expressions (unlike '\') or in file names.

Safety

This is a powerful program that, running with sufficient file permissions, could corrupt the name of every file and directory on your computer (and networked drives) so take care. Preferably make a back-up copy of your files before use, take care that you are running on the directory you intend to run it on and run it in test mode (the '-t ' option) first checking that the changes it is going to make are what want them to be. Treat it with the care you would treat 'rm -rf' on Linux or 'del /s /q *' on Windows.

Installation Options

It does not need fancy installation. Provided Perl has been installed and this program has been download, it should be read to run! The following is just options for making it look tidier.

Changing Installation Directory

If you are only going to use it for a one off job, just put it in directory you want renaming done in and run it from there with 'perl RecursiveRegexpRename.pl' (it might accidentally rename itself but its job will have been done by then) and delete it afterwards.

Alternatively, to keep for later use, put it anywhere listed in the computers 'path' setting (e.g. '/usr/local/bin/' on Linux & 'C:\Windows\System32\' will typically work) or put it wherever you like and add its directory to the computer's 'path' setting.

Getting rid of the '.pl' Filename Extension

The '.pl' on the end that tells the computer that it is a Perl program looks a bit untidy.

On Linux, you can remove it by renaming the program provided you tell your computer it is a Perl script either by always running it explicitly prefixed with 'perl ' or you edit the first line of the program so that that the bit after the '#! ' is the location of your computer's Perl interpreter.

On M$ Windows you cannot remove the '.pl' without using the explicit 'perl ' method but you can avoid needing to type it by adding ';.PL' to the 'PATHEXT' system setting (that tells Windows that '.pl' files are executables and therefore, like '.exe' files, don't need the file extension typed when searching for them in the system path directories).

Shortening the Name

'RecursiveRegexpRename' is nicely descriptive but long to type. That is not a problem if using GNU/Linux/Bash because file names in the system path directories can be autocompleted by pressing the tab key.

Unfortunately on M$ Windows, only items in the current working directory, not the system path directories, can be autocompleted. Hence on Windows I rename the program to the much shorter name 'RRR'. Note that renaming it to simply 'Rename' on Windows is not a good idea as Windows already has a built-in command of that name.

Download

Download RecursiveRegexpRename.pl (6 Kb).

Other Perl Scripts, Disclaimers Etc.

See my computer programs index page for more simple useful computer programs.