Rename files in batch

rename

During importing my music files from backup (thanks to default naming scheme of rhythmbox), I have messed up the file names. Now the looks like:

00 - American Pie.ogg.ogg.ogg.ogg
00 - American Pie.ogg.ogg.ogg.ogg.ogg
00 - another brick in the wall.ogg.ogg.ogg.ogg
00 - another brick in the wall.ogg.ogg.ogg.ogg.ogg
00 - candle_in_the_wind.ogg.ogg.ogg.ogg
00 - candle_in_the_wind.ogg.ogg.ogg.ogg.ogg

While the file should look like

American Pie.ogg
another brick in the wall.ogg
candle_in_the_wind.ogg

And I have (as from wc -l) 3096 such files. How can I restore it in batch mode?
I have tried rename and mmv to work, as given in the ans of this question, but not working (problem with the rename syntax, and for mmv,there is collision).

Any help please?

Best Answer

Using perl-rename (which is one of the two tools that is commonly called rename; the other one uses a very different syntax and can't do this in one step):

rename -f 's/00 - ([^.]*).*/$1.ogg/' *.ogg

The -f or --force option makes rename overwrite any existing files.

The second part is a perl-style regular expression substitution. The basic syntax is s/replacethis/withthis/ The pattern to match -- 00 - ([^.]*).* -- will match all the *.ogg files with names like those in your question. 00 - -- obviously, that just matches the pattern at the beginning of each of the filenames. ([^.]*) is the meat of the regular expression. [^.] will match any single character that isn't a ., while * means 'any number of the previous thing', so [^.]* means 'any number of any characters that aren't .'. The parentheses mark out a capture group (more on that in a second). In regular expressions, . means 'any character' (if you want a literal dot on this side of the substitution you have to escape it, as in: \.), so the final .* means 'any number of any character'.

In the second part of the substitution command, $1 means 'the first capture group' -- that is, that which is contained within the first pair of parentheses (see? Told you I'd come back to it). The .ogg means a literal '.ogg' -- on this side of the substitution, you don't need to escape the dot.

So, roughly translated into English, 's/00 - ([^.]*).*/$1.ogg/' is telling rename to 'take "00 - ", followed by (any number of characters that aren't a dot), then any number of characters; and replace that with the characters contained within the brackets and ".ogg."'.

On some systems, perl-rename is called prename (when rename is taken by the aforementioned other program). On some systems it isn't available at all :(

For recursiveness, you can do one of the following:

shopt -s globstar ## assuming your shell is bash
rename 's/00 - ([^.]*).*/$1.ogg/' **/*.ogg

Or:

find . -name '*.ogg' -exec rename 's/00 - ([^.]*).*/$1.ogg/' {} +
Related Question