regex-rename
Bulk rename tool based on regular expressions to rename multiple files at once.
Quickstart
Renaming multiple files at once:
$ ls # awful names:
b45XDS-01.mp3 QsEW2s-02.mp3 VF7t6L-03.mp3
$ regex-rename '-(\d+).mp3' '\1_NeverGonnaGiveYouUp.mp3' --rename
[2022-04-09 09:19:15] DEBUG matching regular expression pattern to files: pattern=-(\d+).mp3 replacement=\1_NeverGonnaGiveYouUp.mp3 full_match=False dry_run=False
[2022-04-09 09:19:15] INFO renaming file: from=b45XDS-01.mp3 to=01_NeverGonnaGiveYouUp.mp3
[2022-04-09 09:19:15] INFO renaming file: from=QsEW2s-02.mp3 to=02_NeverGonnaGiveYouUp.mp3
[2022-04-09 09:19:15] INFO renaming file: from=VF7t6L-03.mp3 to=03_NeverGonnaGiveYouUp.mp3
[2022-04-09 09:19:15] INFO files renamed: renamed=3 mismatched=0
$ ls # now we're talking:
01_NeverGonnaGiveYouUp.mp3 02_NeverGonnaGiveYouUp.mp3 03_NeverGonnaGiveYouUp.mp3
Installation
pip3 install regex-rename
It requires Python 3.7 (or newer) with pip.
Tutorial
Imagine you have 51 audio files with hideous names like this and you wish to rename them:
Stanislaw+Lem+Invincible+(01).mp3
->01 The Invincible.mp3
Stanis▯aw+Lem+Invincible+(02 ).mp3
->02 The Invincible.mp3
Stanisław_Lem_Invincible (03) .mp3
->03 The Invincible.mp3
- …
Stanis▯aw+Lem+Invincible+(51).mp3
->51 The Invincible.mp3
Specifically, you want to place the episode number at the beginning.
Step 1: Match
Regular Expressions can be tricky. We figured out this pattern may match the files and extracts the episode number:
(\d+).*mp3
First, let's check this pattern in a dry run:
$ regex-rename '(\d+).*mp3'
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-green">DEBUG</span> matching regex pattern <span class="code-green">pattern=</span><span class="code-bold-green">(\d+).*mp3</span> <span class="code-green">dry_run=</span><span class="code-bold-green">True</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> matched file <span class="code-green">file="<span class="code-bold-green">Stanisław_Lem_Invincible (03) .mp3</span>"</span> <span class="code-green">group_1=</span><span class="code-bold-green">03</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> matched file <span class="code-green">file="<span class="code-bold-green">Stanis▯aw+Lem+Invincible+(01).mp3</span>"</span> <span class="code-green">group_1=</span><span class="code-bold-green">01</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> matched file <span class="code-green">file="<span class="code-bold-green">Stanis▯aw+Lem+Invincible+(02 ).mp3</span>"</span> <span class="code-green">group_1=</span><span class="code-bold-green">02</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> matched file <span class="code-green">file="<span class="code-bold-green">Stanis▯aw+Lem+Invincible+(51).mp3</span>"</span> <span class="code-green">group_1=</span><span class="code-bold-green">51</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> files matched <span class="code-green">count=</span><span class="code-bold-green">4</span>
Pay attention to the extracted regex groups.
Step 2: Replace
Now, we'd like to replace all files to a pattern:
\1 The Invincible.mp3
\1
is a first group extracted by the matching pattern (episode number).
Let's test it by adding the replacement pattern:
$ regex-rename '(\d+).*mp3' '\1 The Invincible.mp3'
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-green">DEBUG</span> matching regex pattern <span class="code-green">pattern=</span><span class="code-bold-green">(\d+).mp3</span> <span class="code-green">replacement="<span class="code-bold-green">\1 The Invincible.mp3</span>"</span> <span class="code-green">dry_run=</span><span class="code-bold-green">True</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> matched file
<span class="code-green">from="<span class="code-bold-green">Stanisław_Lem_Invincible (03) .mp3</span>"</span> <span class="code-green">to="<span class="code-bold-green">03 The Invincible.mp3</span>"</span> <span class="code-green">group_1=</span><span class="code-bold-green">03</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> matched file
<span class="code-green">from="<span class="code-bold-green">Stanis▯aw+Lem+Invincible+(01).mp3</span>"</span> <span class="code-green">to="<span class="code-bold-green">01 The Invincible.mp3</span>"</span> <span class="code-green">group_1=</span><span class="code-bold-green">01</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> matched file
<span class="code-green">from="<span class="code-bold-green">Stanis▯aw+Lem+Invincible+(02 ).mp3</span>"</span> <span class="code-green">to="<span class="code-bold-green">02 The Invincible.mp3</span>"</span> <span class="code-green">group_1=</span><span class="code-bold-green">02</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> matched file
<span class="code-green">from="<span class="code-bold-green">Stanis▯aw+Lem+Invincible+(51).mp3</span>"</span> <span class="code-green">to="<span class="code-bold-green">51 The Invincible.mp3</span>"</span> <span class="code-green">group_1=</span><span class="code-bold-green">51</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> files matched <span class="code-green">count=</span><span class="code-bold-green">4</span>
Step 3: Execute
All above commands were just dry-run so that we could experiment with regex patterns.
Once we're sure that everything is matched correctly, we can append --rename
flag,
which does the actual renaming:
$ regex-rename '(\d+).*mp3' '\1 The Invincible.mp3' --rename
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-green">DEBUG</span> matching regex pattern <span class="code-green">pattern=</span><span class="code-bold-green">(\d+).mp3</span> <span class="code-green">replacement="<span class="code-bold-green">\1 The Invincible.mp3</span>"</span> <span class="code-green">dry_run=</span><span class="code-bold-green">False</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> renaming file <span class="code-green">from="<span class="code-bold-green">Stanisław_Lem_Invincible (03) .mp3</span>"</span> <span class="code-green">to="<span class="code-bold-green">03 The Invincible.mp3</span>"</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> renaming file <span class="code-green">from="<span class="code-bold-green">Stanis▯aw+Lem+Invincible+(01).mp3</span>"</span> <span class="code-green">to="<span class="code-bold-green">01 The Invincible.mp3</span>"</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> renaming file <span class="code-green">from="<span class="code-bold-green">Stanis▯aw+Lem+Invincible+(02 ).mp3</span>"</span> <span class="code-green">to="<span class="code-bold-green">02 The Invincible.mp3</span>"</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> renaming file <span class="code-green">from="<span class="code-bold-green">Stanis▯aw+Lem+Invincible+(51).mp3</span>"</span> <span class="code-green">to="<span class="code-bold-green">51 The Invincible.mp3</span>"</span>
<span class="code-gray">[2022-04-01 09:19:15]</span> <span class="code-blue">INFO</span> files renamed <span class="code-green">count=</span><span class="code-bold-green">4</span>
Finally, files are named properly:
01 The Invincible.mp3
02 The Invincible.mp3
03 The Invincible.mp3
- …
51 The Invincible.mp3
Beyond the Regex
regex-rename
also supports some transformations not covered by regular expressions standard:
- Converting to lowercase by adding
\L
before group number:
regex-rename '([A-Z]+).mp3' '\L\1.mp3'
eg.AUDIO.mp3
toaudio.mp3
- Converting to uppercase by adding
\U
before group number:
regex-rename '([a-z]+).mp3' '\U\1.mp3'
eg.audio.mp3
toAUDIO.mp3
- Padding numbers with leading zeros by adding
\P2
,\P3
, … (depending on padding length) before group number:
regex-rename '(\d+).mp3' '\P2\1.mp3'
eg.1.mp3
to01.mp3
- Padding numbers with leading zeros by specifying
--pad-to
parameter:
regex-rename '(\d+).mp3' '\1.mp3' --pad-to=2
eg.1.mp3
to01.mp3
More examples
-
Extract season and episode numbers, eg.
episode-02x05.mkv
toS02E05.mkv
:
regex-rename '(\d+)x(\d+)' 'S\1E\2.mkv' --rename
-
Swap artist with title, eg.
Echoes - Pink Floyd.mp3
toPink Floyd - Echoes.mp3
:
regex-rename '([^-]+) - ([^-]+)\.mp3' '\2 - \1.mp3' --rename
-
Pad leading zeros, eg.
1.mp3
to001.mp3
:
regex-rename '(\d+).mp3' '\P3\1.mp3' --rename
-
Convert to lowercase, eg.
SONG.MP3
tosong.mp3
:
regex-rename '(.+)' '\L\1' --rename
-
Convert to uppercase, eg.
Tool.mp3
toTOOL.mp3
:
regex-rename '(.+)\.mp3' '\U\1.mp3' --rename
-
Add prefix, eg.
Doors.mp3
toThe Doors.mp3
:
regex-rename '(.+)' 'The \1' --full --rename
-
Change extension, eg.
Songbook.apk
toSongbook.zip
:
regex-rename '(.+)\.apk' '\1.zip' --rename
-
Turn directories into prefixes and move files, eg.
Pink Floyd/Echoes.mp3
toPink Floyd - Echoes.mp3
:
regex-rename '(.+)/(.+).mp3' '\1 - \2.mp3' --full --recursive --rename
-
Rename files in different directories, preserving their parent directories, eg.
app/logs/file-001.log
toapp/logs/file_001.txt
:
regex-rename '(.*)/file-([0-9]+).log' '\1/file_\2.txt' --full --recursive --rename
-
Rename files piped from another command like
find
, eg.songs/Jimmi - Voodoo Child.mp3
tosongs/Jimi - Voodoo Child.mp3
:
find -iname '*jimmi*' | regex-rename '(.*)/.* - (.*).mp3$' '\1/Jimi - \2.mp3' --rename
Usage
Enter regex-rename
for help:
$ regex-rename
regex-rename v1.3.0 - Bulk rename tool based on regular expressions to rename multiple files at once
Usage:
regex-rename [OPTIONS] PATTERN [REPLACEMENT]
Arguments:
PATTERN - Regex pattern to match filenames
[REPLACEMENT] - Replacement regex pattern for renamed files. Use \1, \2 syntax to make use of matched groups
Options:
--version - Print version information and exit
-h, --help [SUBCOMMANDS...] - Display this help and exit
-r, --rename - Does actual renaming files instead of just testing replacement pattern
--full - Enforces matching full filename against pattern
--recursive - Search directories recursively
--collate - Compare source filenames with the replaced names
--short - Print output in short, less verbose format without time
--pad-to PAD_TO - Applies padding with zeros with given length on matched numerical groups