Home » Questions » Computers [ Ask a new question ]

Mass renaming, *nix version

Mass renaming, *nix version

I was looking for a way to rename a huge number of similarly-named files, much like this one (a Windows-related question) except that I'm using *nix (Ubuntu and FreeBSD, separately). Just to sum up, while using the shell (Bash, CSH, etc.) how do I mass-rename a number of files such that, for example, the following files:

Asked by: Guest | Views: 87
Total answers/comments: 4
Guest [Entry]

"Try this solution, implemented using a combination of grep and rename. This is assuming you have a whole bunch of directories that you need to rename. If there are just a few, I'd go with the manual approach, with the ""Artist - "" pattern hardcoded for each.

# Rename any mp3 files in the directory hierarchy of type ""a - b.mp3"" to ""b.mp3""
find . -name ""*.mp3"" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;

Explanation of find:
The find command finds all the files with .mp3 extension in the current file hierarchy, and calls the argument passed to -exec for each. Note that within -exec, {} refers to the argument passed by find (file path+name). The \; ensures the ; gets passed to rename and instead of indicating the end of the find command.

The command given above has the -n (no action) switch; hence it will only tell you what would happen if you ran it. I recommend you run this command without the -n switch only after you've run it once and are satisfied with the proposed results.

Now for the regexp.

^ matches start of string.
$ matches the end of the string.
. matches any character.
* means zero or more of the preceeding construct. e.g .* means zero or more characters.
\s stands for any space character.
\S stands for any non-space character.
Anything within () gets captured and is reflected as $1, $2, depending on its position.

The regexp:

Looks for an optional directory structure at the start, captures this in $1: (.*/)
Skips everything till the ""-"" : .*-
Captures the rest of the string, excepting leading and trailing spaces, in $2: (.*)
Rewrites the file as $1$2, which should be ""/path/to/file/""""filename.mp3""

Here's my test run:

/tmp/test$ ls -R
a b c z-unknown.mp3

a3.mp3 a - longer title3.mp3 c.mp3 disc2
a - longer title2.mp3 a - long title.mp3 disc 1 the band - the title.mp3

./a/disc 1:
a - title1.mp3 a - title2.mp3

a - title1.mp3 a - title2.mp3

cd - ab - title3.mp3 cd - title1.mp3 cd - title2.mp3 c.mp3

c-pony2.mp4 c - pony3.mp3 c - pony4.mp3 c-pony.mp3

/tmp/test$ find . -name ""*.mp3"" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3

/tmp/test$ ls -R
a b c unknown.mp3

a3.mp3 c.mp3 disc 1 disc2 longer title2.mp3 longer title3.mp3 long title.mp3 the title.mp3

./a/disc 1:
title1.mp3 title2.mp3

title1.mp3 title2.mp3

c.mp3 title1.mp3 title2.mp3 title3.mp3

c-pony2.mp4 pony3.mp3 pony4.mp3 pony.mp3

Regexp's are tricky business, and I've made many a blunder writing them, so I'd welcome any input on the lack of merit of this one. I know I found quite a few testing this."
Guest [Entry]

For Penguin heads this is easily done in a shell script or AWK script. For us mere mortals you might want to try Midnight Commander. It's on most linux distributions, from a shell prompt type mc -a. You can rename files using regular expressions. I used the article at GeekStuff http://www.thegeekstuff.com/2009/06/how-to-rename-files-in-group/ to help me.
Guest [Entry]

"Here is a simple command-line example. I had the word ""white"" in the middle of the names of a bunch of png files. I wanted to take it out and leave just a single underscore. This did the trick:

for i in *.png; do mv ""$i"" ""${i/white/}""; done"
Guest [Entry]

"Use vidir and then use your editor features to apply the renaming pattern.


vidir - edit directory


vidir [--verbose] [directory|file|-] ...


vidir allows editing of the contents of a directory in a text editor. If
no directory is specified, the current directory is edited.

When editing a directory, each item in the directory will appear on its
own numbered line. These numbers are how vidir keeps track of what items
are changed. Delete lines to remove files from the directory, or edit
filenames to rename files. You can also switch pairs of numbers to swap

Note that if ""-"" is specified as the directory to edit, it reads a list
of filenames from stdin and displays those for editing. Alternatively, a
list of files can be specified on the command line.


vidir *.jpeg
Typical uses.

find | vidir -
Edit subdirectory contents too. To delete subdirectories, delete all
their contents and the subdirectory itself in the editor.

find -type f | vidir -
Edit all files under the current directory and subdirectories.


Joey Hess 2006-2010

Modifications by Magnus Woldrich 2011


Copyright 2006-2011 the vidir ""AUTHOR""s as listed above.

Licensed under the GNU GPL."