I want to rename several hundred files whose names are formatted as follows:

A Study in Scarlet - Arthur Conan Doyle.mobi
Anvil of Stars - Greg Bear.mobi
City and the Stars, The - Arthur C. Clarke.mobi

After renaming I want to reach this naming scheme:

Arthur Conan Doyle - A Study in Scarlett.mobi
Greg Bear - Avil of Stars.mobi
Arthur C. Clarke - City and the Stars, The.mobi

A bonus would be to remove all irregular characters from the name, as there are:

  1. _ [underscores] to replace by blank
  2. %20 to replace by blank
  3. [] to replace with rounded ones ()

I wrote a small bash script to do the job.


# Variables

if [ -f $report ];
    rm -rf $report

echo $'renaming files . . .\n'

for filename in *.$extension
    temp=$(echo $filename | tr '_' ' ' | tr '%20' ' ' | tr '[]' '()' | tr -s ' ' | sed 's/\.[^.]*$//' )

    part1=$(echo $temp | cut -f1 -d-)
    part2=$(echo $temp | cut -f2 -d-)
    new_filename=$(echo "${part2#?} - ${part1%?}.$extension")
    echo $(mv -v "$filename" "$new_filename") | tee -a $report
    if [ $? -ne 0 ]; then
        echo $'\n\nScript FAILED'
        exit 1

echo $'\n\nScript SUCCESSFUL'
exit 0

Create a .bsh file inside the directory in which your .mobi files are stored and paste the above code :

Open a Terminal with Ctrl + Alt + T and navigate to the directory in which your script is stored :

cd /path/to/directory/

To change the permissions of the script :

chmod +x <filename>.bsh

To execute the script :

bash <filename>.bsh

If for some reason the mv fails you will receive an error 'Script FAILED', otherwise you'll get 'Script SUCCESSFUL'.


tr '_' ' ' replace underscores with whitespace

tr '%20' ' ' replace %20 with whitespace

tr '[]' '()' replace square brackets with parentheses

tr -s ' ' replace multiple spaces with one

sed 's/\.[^.]*$//' extracts only the name of the file without the extension

${string#?} remove first character of a string

${string%?} remove last character of a string

mv -v this will show in the terminal which files are being moved. -v stands for verbose.

tee -a changelog.log By default tee command reads from standard input, and writes to standard output and files. -a stands for append.

if [ $? -ne 0 ] checks if the previous command was successful.

report.log stores the previous and latest name of each file.


The script assumes that the filename contains only one dash -

  • Nice script! Have you tested it, and will you add the bonus features? – andy256 May 12 '16 at 0:01
  • @andy256 Script updated to cover the additional features – efthialex May 12 '16 at 0:31

You could use find, xargs, and prename to do this. Read their man pages.

prename applies a Perl "regular expression" to file names, and find and xargs are used to deal with filenames containing Space characters.

I can offer:

find . -type f -iname '*.mobi' -print0 | \
    xargs -0 prename -v -n 's%^(.*/)(.*)( - )(.*)\.mobi%$1$4$3$2.mobi%'

And, it worked for me:

  $ find . -maxdepth 1 -name '*.mobi' -print0 | xargs -0 prename -n -v 's%^(.*/)(.*)( - )(.*)\.mobi%$1$4$3$2.mobi%' 
./A Study in Scarlet - Arthur Conan Doyle.mobi renamed as ./Arthur Conan Doyle - A Study in Scarlet.mobi

You could use additional executions of prename to change your other funny characters. Be sure to read man perlre to learn about Perl Regular Expressions. If you haven't used regular expressions before, a quick-start introduction is available in man perlrequick, and a longer tutorial introduction is available in man perlretut.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.