0

I would like to normalize filenames with the help of a – how I would call it – "mapping list" in python.


For instance I have some files named like this:

Abb. 1 - Streßfaktor   ìmpersóna.jpg
Abb. 2 - Änderungsverlauf.jpg
Abb. 3 — Senôjarîolé.jpg

My aim is to get this:

Abb_1_Stressfaktor_impersona.jpg
Abb_2_Aenderungsverlauf.jpg
Abb_3_Senojariole.jpg

The rules are quite simple and may be stored in a "mapping list" with regular expressions:

"\s+|.|,|;|-|–|—" : "_"
"ß" : "ss"
"ä" : "ae"
"ü" : "ue"
"ö" : "oe"
"á|â|à|ā|ă|ą|ã|å" : "a"
"í|í|ì|ï|ĩ|ī|ĭ|į|ǐ" : "i"
"_+" : "_"

So before the : there’s the search-string in regex, after the : there’s the replace-string.


I already tried:

import os

current_path = os.getcwd()
print('Current path: %s' %current_path)

filenames = os.listdir(current_path)
for filenamen in filnames:
    os.rename(filename, filename.replace(" ", "_"))
    os.rename(filename, filename.replace(".", "_"))
    os.rename(filename, filename.replace(",", "_"))
    os.rename(filename, filename.replace(";", "_"))
    os.rename(filename, filename.replace("-", "_"))
    os.rename(filename, filename.replace("–", "_"))
    os.rename(filename, filename.replace("—", "_"))
    os.rename(filename, filename.replace("ß", "ss"))
    os.rename(filename, filename.replace("ä", "ae"))
    os.rename(filename, filename.replace("ü", "ue"))
    os.rename(filename, filename.replace("ö", "o"))
    os.rename(filename, filename.replace("á", "a"))
    os.rename(filename, filename.replace("â", "a"))
    os.rename(filename, filename.replace("à", "a"))
    …

But the problem with this code is, that as soon as the first replacement is made, I get the FileNotFoundError, which is logical: The filename was changed and therefore the "original" file does not exist anymore.


I already searched for a solution with a "mapping list", but I did not find anything handy to achieve the given aim.

Does anybody know how to solve this problem?

typopaul
  • 81
  • 4

1 Answers1

1

If you don't call os.rename after each replace (just assign the result of the replace method in a temporary variable), your approach should work, e.g.:

filenames = os.listdir(current_path)
new_name = ""
for filename in filenames:
    new_name = filename.replace(".", "_").replace(",", "_")  # ...
    os.rename(filename, new_name)

You could also store your replacements in a dictionary and apply them in a nested loop, e.g. (using regular expressions):

replacements = {
    "ß": "ss",
    "ä": "ae",
    # ...
}

filenames = os.listdir(current_path)
new_name = ""
for filename in filenames:
    new_name = filename
    for key, value in replacements.items():
        new_name = re.sub(key, value, new_name)
    os.rename(filename, new_name)

An alternative approach that performs all substitutions at once using regular expressions is shown in this answer.

user7217806
  • 2,014
  • 2
  • 10
  • 12