0

I would like to rename the following files from

l4_0_0.m4a
l4_0_1.m4a
l4_0_2.m4a
l5_0_0.m4a
l5_0_1.m4a
l5_0_2.m4a
l6_0_0.m4a
.
.
.
l11_0_2.m4a

To the following names

l5_0_0.m4a
l5_0_1.m4a
l5_0_2.m4a
l6_0_0.m4a
l6_0_1.m4a
l6_0_2.m4a
l7_0_0.m4a
.
.
.
l12_0_2.m4a

I am developing an application that used to have 12 levels, I had to add a level before level 5 (l4__) therefore, I have to rename all the levels after level five. level 5 (l4__) will be level 6(l5__)

I am new to python and regular expressions. Any help will be appreciated it. Thanks

  • Hello Suha, what did you try ? – Zulu Dec 02 '18 at 02:36
  • Hi @Zulu, I tried to manipulate the code in the link below but it did not work since I have two "_" in my file name, also in the like the file first name first part is constant which is not the case for my files: https://stackoverflow.com/questions/17748228/rename-multiple-files-in-python – Infinite Looper Dec 02 '18 at 09:00
  • Are you willing to *learn* python regular expressions or are you expecting somebody else to help you out with a solution? – greybeard Dec 02 '18 at 09:16
  • I want to learn it but this question although is trivial for @greybeard is not for me – Infinite Looper Dec 02 '18 at 09:38

2 Answers2

2

Using a regular expression with symbolic group names will allow you to easily access the parts of the file name you wish to manipulate. I used a class as I thought you may want to add additional functionality to the renaming process such as sub levels or the lowest level.

#!/usr/bin/env python3

import re
import os


class NamedFile(object):
    file_mask = re.compile(r"(?P<PREFIX>l)(?P<LEVEL>\d+)_(?P<SUBLEVEL>\d+)_(?P<LOWLEVEL>\d+)\.(?P<EXTENSION>m4a)")
    file_format = "{PREFIX}{LEVEL}_{SUBLEVEL}_{LOWLEVEL}.{EXTENSION}".format

    @classmethod
    def files(cls, path):
        for f in sorted(os.listdir(path)):
            groups = cls.file_mask.match(f)
            if groups is not None:
                yield (path, f, groups.groupdict())

    @classmethod
    def new_name(cls, groups, increment):
        level = int(groups["LEVEL"]) + 1
        groups["LEVEL"] = level
        return cls.file_format(**groups)

    @classmethod
    def rename(cls, path, increment):
        for path, f, file_parts in NamedFile.files(path):
            new_filename = cls.new_name(file_parts, increment)
            abs_new = os.path.join(path, new_filename)
            abs_old = os.path.join(path, f)
            os.rename(abs_old, abs_new)


if __name__ == "__main__":
    print("===Original file names===")
    for path, f, file_parts in NamedFile.files("."):
        print(f)

    NamedFile.rename(".", 1)

    print("===New file names===")
    for path, f, file_parts in NamedFile.files("."):
        print(f)
Kristian
  • 482
  • 2
  • 8
1

The following should do it. Run it in the directory those files are in, and it will produce the new files in a directory called out.

from os import listdir, makedirs
from os.path import exists, isfile, join
import re
import shutil

output_dir = 'out'

files = [f for f in listdir('.') if isfile(join('.', f)) and f.endswith('.m4a')]

if not exists(output_dir):
    makedirs(output_dir)

for f in files:
    level, suffix = re.match(r'^l([0-9]+)(_.+)', f).groups()
    shutil.copyfile(f, join(output_dir, 'l%d%s' % (int(level) + 1, suffix)))

Result:

$ ls
l4_0_0.m4a  l4_0_1.m4a  l4_0_2.m4a  l5_0_0.m4a  l5_0_1.m4a  l5_0_2.m4a  rename.py

$ python rename.py
$ ls out
l5_0_0.m4a  l5_0_1.m4a  l5_0_2.m4a  l6_0_0.m4a  l6_0_1.m4a  l6_0_2.m4a
cody
  • 11,045
  • 3
  • 21
  • 36