Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

This question already has an answer here:

I use xmbc to view my tv shows. Before I began using xmbc, I batch downloaded the first few seasons of "Bleach". What can I say, I'm an anime fan ;-). These are named: "bleachxx.mp4" where xx is the episode number in respect to the whole series, not to the season. so "bleach21.mp4" is the 1st episode of the second season and 21st overall. The files themselves are, however, divided into their own season folders.

I know you can use the "rename" command to batch rename files. After much tinkering with it using this guide: http://tips.webdesign10.com/how-to-bulk-rename-files-in-linux-in-the-terminal I got this command:

rename -n 's/.*(\d{2}).*$/Bleach S0XE$1/' *

The problem is that the command will rename all the files into "Bleach S0XExx" but because the files have the overall file numbers, bleach52.mp4 --> 'Bleach S03E52.mp4' when there obviously aren't 52 episodes in season 3.

I would like to know, then, if there is any way to apply mathematical operations to the file renaming. This would solve the problem as I could subtract The number of episodes in the previous seasons by the overall number and essentially get the season number.

Example: If there are 20 episodes in season 1, then 25-20=5 so the 25th episode is the 5th of season 2 and renaming would carry out as normal.

So, is there anyway to change the values of renaming by applying math operations?

P.S. I'm sorry for the long explanation but I wasn't sure how to or if my question would be clear without it.

share|improve this question

marked as duplicate by Eliah Kagan, Radu Rădeanu Sep 12 at 12:36

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
Eh... you lost me at math :) –  RolandiXor Oct 27 '11 at 0:23

5 Answers 5

up vote 5 down vote accepted

If you're dedicated enough to tinker with regular expressions (in the example you're provided) then I suggest just to go one step farther and write a small script - say, in Python. This way you'll be able to perform absolutely any transformations to file names.

I would estimate the python script would be no longer than 15-20 lines long so it's definitely not a huge task. Using just regexps, as you're trying, is much more limited.

Here's my take on such script:

#!/usr/bin/python
import os,re

files = os.listdir('.')

SEASONS = (
 (1, 1, 3), # the format is - season number, first episode, last episode
 (2, 50,52),
 (3, 53,55),
 (4, 56,99),
)

for f in files:
    # skip all files which are not .mp4
    if not f.endswith(".mp4"):
        continue

    # find the first number in the filename
    matches = re.findall("\d+", f)
    if not len(matches):
       print "skipping", f
    num = int(matches[0])

    for season in SEASONS:
        if num <= season[2]:
            season_num = season[0]
            ep_num = num - season[1] + 1
            new_file_name = "BleachS%02dE%02d.mp4" % (season_num, ep_num)
            # This is for testing
            print "%s ==> %s" % (f, new_file_name)
            # Uncomment the following when you're satisfied with the test runs
            # os.rename(f, new_file_name)
            break

print "Done"

It looks like I under-estimated the script size (it's 36 lines atm), though I'm sure if you go to stackoverflow with this code, you'll get many suggestions which are much more elegant

And just because I said it can be done in 15 lines... the following is 20 lines, 5 of which is configuration :P

#!/usr/bin/python
import os, re, glob

SEASONS = (
 {'num':1, 'first':1, 'last':3}, # the format is - season number, first episode, last episode
 {'num':2, 'first':50, 'last':52},
 {'num':3, 'first':53, 'last':55},
 {'num':4, 'first':56, 'last':99},
)

files = glob.glob('bleach*.mp4')
for f in files:
    num = int(re.findall("\d+", f)[0])  # find the first number in the filename
    for season in SEASONS:
        if num > season['last']: continue
        new_file_name = "BleachS%02dE%02d.mp4" % (season['num'], num - season['first'] + 1)
        print "%s ==> %s" % (f, new_file_name) # This is for testing
        # os.rename(f, new_file_name) # Uncomment this when you're satisfied with the test runs
        break
share|improve this answer
    
Could you give me a basic idea of how to do this, or links to tutorials. I have never written code so I'm not sure how smoothly I can do this. First of all, how do I write in a particular language? (yes, Iḿ that of a noob, but I definitley want to learn) –  DeoxNa Oct 27 '11 at 1:01
    
Haha, yours is a lot cleaner than mine. –  Kris Harper Oct 27 '11 at 2:09
    
It worked! (both of them) Thanks a lot! Though I must say the first time the output didn't come out right (in the test) for either of them. Then I noticed that in my post I didn't mention that the files are actually named "bleachxx-lq.mp4", so i corrected that in line 13 of your final script, and voila! Something weird happened then, though. I once again tried the script using your first script and it worked correctly, even though I hadn't modified that one at all (beyond season numbers). Go figure... Anyway thanks once more, but, just out of curiosity, why do both scripts work now? –  DeoxNa Oct 27 '11 at 3:13

I wrote you a python script

import sys
import os
import glob
import re

def rename():
    episode_counts = (0, 20, 41, 63)
    episode_pairs = []
    for index, num in enumerate(episode_counts):
        if index < len(episode_counts) - 1:
            episode_pairs.append((num, episode_counts[index+1]))

    episodes = glob.glob(os.path.join(sys.argv[1], '*'))

    for episode in episodes:
        match = re.search('.*(\d{2}).*$', os.path.basename(episode))
        episode_num = match.group(1)

        for season, pair in enumerate(episode_pairs):
            if int(episode_num) in range(pair[0]+1, pair[1]+1):
                dirname = os.path.dirname(episode)
                path = os.path.join(dirname, 'Bleach S{0}E{1}'.format(season+1, episode_num))
                os.rename(episode, path)

if __name__ == "__main__":
    rename()

I'm really new to python (which is partly why I wrote this, for practice), so it's probably not the best script in the world. But I tried it on a few test files and it seems to work.

Just edit the line near the top episode_counts = ... to the last episode numbers for a season. I put in the first three from this page.

Save the code as something like episode_renamer.py and use it with python episode_renamer.py /path/to/episodes/.

share|improve this answer
    
It's interesting to see someone else's approach to the same problem :) Nice! –  Sergey Oct 27 '11 at 2:28
    
Thanks! I used Sergey's on my actual files, but tried yours on some test files. It gave me the following errors: Traceback (most recent call last): File "/home/david/Documents/1st", line 27, in <module> rename() File "/home/david/Documents/1st", line 14, in rename episodes = glob.glob(os.path.join(sys.argv[1], '*')) IndexError: list index out of range You said you wanted practice in python, so this can help you by trying to find the errors. I'll keep it your script though, as I also want to learn it. Anyway, thank you for your help! –  DeoxNa Oct 27 '11 at 3:18
    
@user600: You were supposed to use "python episode_renamer.py /path/to/episodes/" syntax - I think the script will fail if you don't provide the path to folder –  Sergey Oct 27 '11 at 3:39

There is a file manager called Thunar available in the repository which has a bulk rename option.

See this site for more information: http://thunar.xfce.org/pwiki/documentation/bulk_renamer

You can install thunar in the Software Center or on the command line with:

sudo apt-get install thunar

There are other ways of doing this in bash, or by writing some code, but a graphical tool will probably get you what you want faster.

share|improve this answer

I'm developing a cross-platform desktop application that lets you rename a set of files from a specified pattern to another one. User can specify both of the patterns.

You can download it from this link (it's called: file-renamer-swt). And here is the project main site.

share|improve this answer

To continue flogging this horse... if this is a one-time rename I would do something disposable like:

cd /path/to/stuff
ls bleach*-lq.mp4 >x
paste x x >y
sed 's-^-mv -' <y >z
vim z    # or use your favorite editor
           # to rename the files manually
bash -x z
rm x y z

If you will be using it more than once, and for more than one kind of episode... then python is the way to go, and the examples above are just fine.

share|improve this answer

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