shutil.rmtree用于删除只读文件

21
我想在Python中使用shutil.rmtree来删除一个目录。该目录包含一个由git标记为只读和隐藏的.git控制目录。
只读标志会导致rmtree失败。在PowerShell中,我会使用"del -force"来强制删除只读标志。Python中是否有类似的方法?我真的不想走整个目录树两次,但是rmtree的onerror参数似乎不能重试操作,因此我无法使用。
def set_rw(operation, name, exc):
    os.chmod(name, stat.S_IWRITE)

shutil.rmtree('path', onerror=set_rw)

2
你尝试在onerror回调函数中删除文件了吗? - Fred Foo
.git 是只读的这一点很奇怪。 - wim
如果您想要,我可以发布一个解决方案。您可以先更改文件的权限,然后再进行编辑。 - wnnmaw
@wnnmaw 这不意味着需要对树进行双重遍历,使用 os.walk 获取所有内容并强制 RW 模式吗?如果这就是你的意思,我知道如何做到这一点(正如我所说,我只是想尽可能避免这样做)。但还是谢谢你的建议。 - Paul Moore
2
你不需要走两遍,只需在更改权限时一并删除文件。此外,我不确定你使用的是什么系统,但如果是Windows,则权限是继承的,因此如果设置正确,您应该能够更改顶层并使其向下级联。 - wnnmaw
显示剩余2条评论
4个回答

44
经过进一步调查,以下方法似乎有效:
def del_rw(action, name, exc):
    os.chmod(name, stat.S_IWRITE)
    os.remove(name)

shutil.rmtree(path, onerror=del_rw)

换句话说,在onerror函数中实际上删除文件。(你可能需要在onerror处理程序中检查目录,并在那种情况下使用rmdir - 我不需要,但这可能只是与我的问题有关的特定情况。)

0

shutil.rmtree 用于删除非空目录(删除树)。


    import os
    import stat
    import shutil
    def del_ro_dir(dir_name):
        '''Remove Read Only Directories'''
        for (root, dirs, files) in os.walk(dir_name, topdown=True):
            os.chmod(root,
                # For user ...
                stat.S_IRUSR |
                stat.S_IWUSR |
                stat.S_IXUSR |
                # For group ...
                stat.S_IWGRP |
                stat.S_IRGRP |
                stat.S_IXGRP |
                # For other ...
                stat.S_IROTH |
                stat.S_IWOTH |
                stat.S_IXOTH
            )
        shutil.rmtree(dir_name)

    if __name__ == '__main__':
        del_ro_dir('dir_name_here')

如果只想删除一个文件,可以使用以下代码:


    import os
    import stat
    def rmv_rof(file_name):
        '''Remov Read Only Files'''
        if os.path.exists(file_name):
            os.chmod(file_name, stat.S_IWRITE)
            os.remove(file_name)
        else:
            print('The file does not exist.')
    rmv_rof('file_name_here')

您可以在这里阅读详细信息:

https://docs.python.org/3/library/os.html#os.chmod

https://docs.python.org/3/library/stat.html#module-stat

https://docs.python.org/3/library/shutil.html#rmtree-example


0
这是从shutil文档中直接复制的rmtree示例(可能是在原始帖子之后添加的)。
import os, stat
import shutil

def remove_readonly(func, path, _):
   "Clear the readonly bit and reattempt the removal"
   os.chmod(path, stat.S_IWRITE)
   func(path)

shutil.rmtree(directory, onexc=remove_readonly)
请注意与接受的答案相比,存在一个小的差异:上面的示例使用了func参数,而不是显式调用os.remove
另外请注意,从Python 3.12开始,onerror已被弃用,将被onexc取代。

0

你可以采用快速而简单的方法,使用subprocess.check_call(["rm", "-rf", filename])。但是在Windows上可能无法正常工作。


考虑在filename之前添加"--"作为第三个参数--这样即使文件名以连字符开头,代码也能正确运行。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接