目录名称在for循环中未更改

问题描述 投票:0回答:2

[我正在尝试递归重命名目录中的所有子目录和文件,以摆脱德语变音符号,并用其“安全”副本替换它们(即用“ ue”替换“ü”)。

为了重命名,我找到了以下代码

def remove_umlaut(string):
    """
    Removes umlauts from strings and replaces them with the letter+e convention
    :param string: string to remove umlauts from
    :return: unumlauted string
    """
    u = 'ü'.encode()
    U = 'Ü'.encode()
    a = 'ä'.encode()
    A = 'Ä'.encode()
    o = 'ö'.encode()
    O = 'Ö'.encode()
    string = string.encode()
    string = string.replace(u, b'ue')
    string = string.replace(U, b'Ue')
    string = string.replace(a, b'ae')
    string = string.replace(A, b'Ae')
    string = string.replace(o, b'oe')
    string = string.replace(O, b'Oe')
    string = string.decode('utf-8')
    return string

而且单独测试时有效。我的递归重命名功能如下:

def renameInvalid(root):
    for f in os.listdir():
        old = f 
        f = remove_umlaut(f)
        if old != f:                              
            os.rename(old,f)                
            print("renamed " + old + " to " + f )
        if os.path.isdir(f):
            os.chdir(f)
            renameInvalid(".")
            os.chdir("..")  

当我在解释器中对此进行测试时,问题似乎是,在通过os.listdir()进行迭代时,无法更改字符串。既不具有上述功能,也不具有正则表达式。

在Mac和Windows上进行了测试。

哪里出错了?

python replace diacritics listdir
2个回答
0
投票

尝试一下:

from pathlib import Path

def remove_umlaut(string_with_umlaut: str) -> str:
    """
    Removes umlauts from strings and replaces them with the letter+e convention
    :param string_with_umlaut: string to remove umlauts from
    :return: unumlauted string
    """
    umlaut_alternatives = {
         'ü': 'ue',
         'Ü': 'Ue',
         'ä': 'ae',
         #... etc,
    }
    string_without_umlaut = string_with_umlaut
    for umlaut, no_umlaut in umlaut_alternatives.items():
        string_without_umlaut = string_without_umlaut.replace(umlaut, no_umlaut)
    return string_without_umlaut

def rename_invalid(root: str):

    for file in Path(root).glob("**/*"):
        file_new = remove_umlaut(file.name)
        if file_new != file.name:
            print(f"Rename {file.name} to {file_new}")
            file.rename(file.parent / file_new)

0
投票

感谢Dan在我想出的评论中的帮助。

带有Umlaut的字母可以在UTF-8中以两种方式表示:预分解和分解。前者将它们表示为一个字符,而后者则将其表示为“正常”字符加字符¨

我上面的脚本适用于预设形式,但是在Mac中从目录读取时,它们以分解形式给出。如果遇到相同的问题,则这里的代码与上面相同(即使可能是很多方法),但与分解的变音符兼容:

def remove_umlaut(name):
    """
    Removes umlauts from names and replaces them with the letter+e convention
    :param name: name to remove umlauts from
    :return: unumlauted name
    """
    u = b'u\xcc\x88'
    U = b'U\xcc\x88'
    a = b'a\xcc\x88'
    A = b'A\xcc\x88'
    o = b'o\xcc\x88'
    O = b'O\xcc\x88'
    ampersand = b'&'
    name = name.encode('utf8')
    name = name.replace(u, b'ue')
    name = name.replace(U, b'Ue')
    name = name.replace(a, b'ae')
    name = name.replace(A, b'Ae')
    name = name.replace(o, b'oe')
    name = name.replace(O, b'Oe')
    name = name.replace(ampersand, b'und')
    name = name.decode('utf8')
    return name

def renameInvalid(root):
    for f in os.listdir(root):
        old = f 
        f = remove_umlaut(f)
        if old != f:                              
            os.rename(old,f)                
            print("renamed " + old + " to " + f )
        if os.path.isdir(f):
            os.chdir(f)
            renameInvalid(".")
            os.chdir("..")
© www.soinside.com 2019 - 2024. All rights reserved.