'tuple'对象没有属性'replace'

时间:2018-10-13 13:53:11

标签: python string replace filenames os.walk

我已经阅读过有关此错误的先前文章。但是,这对我没有帮助。因此,我再次提请注意。代码如下。

import os
replacements = {':': '_', '+': '_'}

for fn in os.walk('/media/ambijat/Dataworld/f23/Dropbox/ttgis'):
    nn = fn
    for k, v in replacements.items():
        nn = nn.replace(str(k), str(v))
        if nn != fn:
             os.rename(fn, nn)

此命令在运行时出现错误'tuple' object has no attribute 'replace',并且似乎出现了错误。我正在使用dict替换文件名中的特殊字符,例如[,&<>*?|\";+:'() ]。有没有更好的办法做到这一点。谢谢。

3 个答案:

答案 0 :(得分:4)

os.walk产生元组:

  

对于树根目录中的每个目录   目录顶部(包括顶部本身),它会生成一个 3元组(目录路径,   目录名,文件名)

要仅提取文件名,请使用索引或序列解压缩。这些都可以使用:

nn = fn[-1]
nn = fn[2]
_, _, nn = fn

或者,正如@AntonvBR指出的那样,您可以在for可迭代循环的定义中使用序列解压缩:

for _, _, fn in os.walk('/media/ambijat/Dataworld/f23/Dropbox/ttgis'):
    nn = fn
    # as before..

答案 1 :(得分:2)

在您的第一段代码中,fn是一个元组,因为os.walk()返回一个dirpath(字符串),dirnames(列表),文件名(list)的元组。因此,当将其分配给nn时,nn成为元组,而依次使用nn.replace(k, v)将不起作用,因为元组没有方法replace

在第二段代码中,nn现在等于fn[2](目录名列表)。不幸的是,列表也没有replace方法。假设您要替换文件名中的所有:+,则需要遍历以下每个文件名:

我在代码中观察到并更改的其他内容:

  • os.walk返回的文件名不包含文件的完整路径,这意味着如果脚本不在与您所在的目录相同的目录中运行,os.rename可能找不到文件重命名文件。因此,我也在重命名期间合并了path
  • os.rename之后,目录中的文件将被重命名,但是代码读取的文件名仍将相同。因此,您还必须在代码中更改文件名。

所以:

import os
replacements = {':': '_', '+': '_'}

for fn in os.walk('/media/ambijat/Dataworld/f23/Dropbox/ttgis'):
    path = fn[0]
    nn = fn[2]
    for filename in nn:
        newname = filename
        for k, v in replacements.items():
            newname = newname.replace(str(k), str(v))
            if newname != filename:
                 os.rename(os.path.join(path, filename), os.path.join(path, newname))
                 filename = newname

尽管我会通过以下建议再减少一条代码行:

import os
replacements = {':': '_', '+': '_'}

for path, _, filenames in os.walk('/media/ambijat/Dataworld/f23/Dropbox/ttgis'):
    for filename in filenames:
        newname = filename
        for k, v in replacements.items():
            newname = newname.replace(k, v)
            if newname != filename:
                 os.rename(os.path.join(path, filename), os.path.join(path, newname))
                 filename = newname

答案 2 :(得分:0)

问题在于线路

nn = nn.replace(str(k), str(v))

os.walk根据the Python docs返回一个(dirpath, dirnames, filenames)形式的元组序列。因此,您尝试在元组上调用.replace()方法,这会给您带来错误,因为tuple类没有这样的方法。我认为您打算使用str.replace()方法。

以下一些代码应该可以工作(在我为此目的在我的计算机上创建的某些目录中进行了测试):

import os
replacements = {':': '_', '+': '_'}

for directory in os.walk('/media/ambijat/Dataworld/f23/Dropbox/ttgis'):
    filenames = directory[-1]

    for k, v in replacements.items():

        for filename in filenames:
            newname = filename.replace(k, v)

            if newname != filename:
                os.rename(directory[0]+'\\'+filename, directory[0]+'\\'+newname)
相关问题