Question

I want to use shutil.rmtree in Python to remove a directory. The directory in question contains a .git control directory, which git marks as read-only and hidden.

The read-only flag causes rmtree to fail. In Powershell, I would do "del -force" to force removal of the read-only flag. Is there an equivalent in Python? I'd really rather not walk the whole tree twice, but the onerror argument to rmtree doesn't seem to retry the operation, so I can't use

def set_rw(operation, name, exc):
    os.chmod(name, stat.S_IWRITE)

shutil.rmtree('path', onerror=set_rw)
Était-ce utile?

La solution

After more investigation, the following appears to work:

def del_rw(action, name, exc):
    os.chmod(name, stat.S_IWRITE)
    os.remove(name)
shutil.rmtree(path, onerror=del_rw)

In other words, actually remove the file in the onerror function. (You might need to check for a directory in the onerror handler and use rmdir in that case - I didn't need that but it may just be something specific about my problem.

Autres conseils

shutil.rmtree is used to delete directories that are not empty (remove tree).


    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')

To delete a file only, you can use the following code:


    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')

You can read detailed information 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

You could just go with the quick-and-dirty method and do subprocess.check_call(["rm", "-rf", filename]). Likely won't work on Windows though.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top