[我正在尝试递归重命名目录中的所有子目录和文件,以摆脱德语变音符号,并用其“安全”副本替换它们(即用“ 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上进行了测试。
哪里出错了?
尝试一下:
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)
感谢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("..")