Rename a group of files at once

One thing I need to do pretty much every day, is rename a batch of files, using a set of predetermined rules. A few months back, when I was still on Windows, I used to have a tool to do just that, so logically I started looking for a "replacement" now that I'm on Linux.

However, while I did find a few batch renaming utilities, none of them would really fill all the checkboxes of my requirements list. Either because they didn't provide the "rules" I was looking for, or because they would rename files after each rule has been applied, or because they couldn't be used from scripts (that way I wanted), or whatever the reason.

So, I just went ahead and made (yet another) one:

molt: batch renaming utility

As said, the aim of this little tool is to rename a group of files, using a set of rules.

molt will, for each file, apply all the rules to determine the new name. It will make sure those new names are "free," as in not already in use; and handles "avoidable conflicts" - when a file's new name is taken by another file to be renamed (performing two-steps renaming with a temporary name if needed).

By default, molt will only attempt to rename anything if no errors or conflicts were found (though this could be changed via option --continue-on-error)


Rules are the heart of molt, since they're what determines the new names will be. molt comes in with a few rules, currently they are:

--upper : convert to upper case

--lower : convert to lower case

--camel : convert to Camel Case

--list : use list of new news read from stdin

--sr search[/replacement[/options]] : perform (optionally case insensitive) search and replace operation. Removes search if no replacement is specified

--regex pattern[/replacement[/options]] : same as above, but using regular expressions

--vars : resolves variables

--tpl template : set all filenames to template and, so it's actually useful, resolves variables

That's it, but I might add a few more, such as ways to insert a string at a given place, and maybe remove a string by location as well. (And if you have needs/ideas for rules, let me know.)

Another thing to note: molt comes with plugin support, which can provide new rules.


You can use "variables" in the new flenames, which will be resolved independently for each file. The syntax is to put the variable's name in between dollar signs, e.g: $FOOBAR$

Some variables can also support optional parameters. Those can be specified using colon as separator, e.g: $FOOBAR:PARAM1:PARAM2$

Variables are not automatically resolved, you need to use the rule --vars in order to have them resolved, which gives you the ability to determine when resolving happens, as well as continue processing with more rules afterwards.

Currently molt only supports one variable :

NB[:digits[:start[:increment]]] : resolves to a number, starting at start (default: 1) and incremented by increment (default: 1; can be negative) for each file using it. The number will have at least digits digits, padded with zeros.

This means that is you use the variable on only some of the files (e.g. through a rule like --sr) then counter will only be incremented for each of those files, "skipping" the files whose name doesn't include the variable.

However, if used multiple times within the same name, it'll only be incremented once.

As with rules, plugins can provide new variables as well. Speaking of which,

plugin: magicvar

molt comes with plugin support, so new rules and/or variables can be added easily. And since I wanted to make one, both as an example and a way to make sure the whole thing worked as expected, molt comes with a plugin called magicvar.

What it does is provide a new variable, whose name is a underscore. The idea is that this variable requires one parameter, which is the "actual name" of the variable you want to include. And resolving it will be done through an external process.

For example, let's say you want to be able to use a variable "type" to get the type of file, as returned by command file

First you need to create a configuration file, in ~/.config/molt/magicvar.conf and within section variables you define which command line shall be run to resolve the variable. You can use %F as placeholder for the path/filename of the file, as well as %P for any additional parameters given to the magic variable (in molt's new name).

For example, with:

type=file -b %F

Then, using $_:type$ in molt will have magicvar run file -b for each file, and use its output as value for the variable (auto-stripping the trailing \n).

This could e.g. be used to get EXIF data from pictures, ID3 tags from MP3 files, that sort of things. (Although a dedicated plugin might be better/faster, especially since it could cache data, to e.g. read the file once for all possible variables.)

Output & return value

molt provides two outputs that can be of use from scripts: only the new names of files (or, if they haven't - or couldn't - be renamed, their current names), or both their old and new names.

It returns 0 in case of success, else uses bit fields with the following :

1 Syntax error (e.g. invalid option, etc)

2 File not found

4 Rule failed

8 Invalid new name

16 New name already in use

32 Internal conflict (multiple files with the same new name)

64 Rename operation failed


molt is not an advanced mv, it is a (batch) renaming utility, and as such only ever tries to rename files (whereas mv can also effectively move files).

While with certain options it can also seems like it moves file, this will only work if said files remain on the same file system. Trying to have a file moved to another file system is likely to fail with an error such as "Invalid cross-device link"


There you go. Hopefully this might be useful to some. molt is released under GNU GPL v3+ The source code is available on this BitBucket repository.

You can also find a PKGBUILD in the AUR.

And of course bug reports, suggestions or any other form of constructive criticism is very much welcome.

Top of Page