如何删除/删除Python不为空的文件夹?

时间:2008-11-19 20:15:39

标签: python file

当我尝试删除非空文件夹时,我收到'访问被拒绝'错误。我在尝试中使用了以下命令:os.remove("/folder_name")

删除/删除非空文件夹/目录的最有效方法是什么?

20 个答案:

答案 0 :(得分:1184)

import shutil

shutil.rmtree('/folder_name')

Standard Library Reference: shutil.rmtree

按照设计,rmtree在包含只读文件的文件夹树上失败。如果要删除文件夹而不管它是否包含只读文件,请使用

shutil.rmtree('/folder_name', ignore_errors=True)

答案 1 :(得分:124)

来自os.walk()上的the python docs

# Delete everything reachable from the directory named in 'top',
# assuming there are no symbolic links.
# CAUTION:  This is dangerous!  For example, if top == '/', it
# could delete all your disk files.
import os
for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        os.remove(os.path.join(root, name))
    for name in dirs:
        os.rmdir(os.path.join(root, name))

答案 2 :(得分:101)

import shutil
shutil.rmtree(dest, ignore_errors=True)

答案 3 :(得分:17)

你可以使用python 3.4中的

import pathlib

def delete_folder(pth) :
    for sub in pth.iterdir() :
        if sub.is_dir() :
            delete_folder(sub)
        else :
            sub.unlink()
    pth.rmdir() # if you just want to delete dir content, remove this line

其中pthpathlib.Path个实例。很好,但可能不是最快的。

答案 4 :(得分:7)

import os
import stat
import shutil

def errorRemoveReadonly(func, path, exc):
    excvalue = exc[1]
    if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
        # change the file to be readable,writable,executable: 0777
        os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)  
        # retry
        func(path)
    else:
        # raiseenter code here

shutil.rmtree(path, ignore_errors=False, onerror=errorRemoveReadonly) 

如果设置了ignore_errors,则忽略错误;否则,如果设置了onerror,则调用它来处理带有参数的错误(func,path,exc_info),其中func是os.listdir,os.remove或os.rmdir; path是导致它失败的那个函数的参数;和exc_info是sys.exc_info()返回的元组。如果ignore_errors为false且onerror为None,则会引发异常。此处输入代码

答案 5 :(得分:5)

来自docs.python.org

  

此示例显示如何在Windows上删除目录树   一些文件的只读位设置。它使用了onerror   回调清除readonly位并重新尝试删除。任何   随后的失败将会传播。

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, onerror=remove_readonly)

答案 6 :(得分:5)

只需要一些python 3.5选项即可完成上述答案。 (我很想在这里找到它们。)

import os
import shutil
from send2trash import send2trash # (shutil delete permanently)

删除文件夹,如果为空

root = r"C:\Users\Me\Desktop\test"   
for dir, subdirs, files in os.walk(root):   
    if subdirs == [] and files == []:
           send2trash(dir)
           print(dir, ": folder removed")

如果文件夹包含此文件,则删除该文件夹

    elif subdirs == [] and len(files) == 1: # if contains no sub folder and only 1 file 
        if files[0]== "desktop.ini" or:  
            send2trash(dir)
            print(dir, ": folder removed")
        else:
            print(dir)

删除文件夹(如果它只包含.srt或.txt文件)

    elif subdirs == []: #if dir doesn’t contains subdirectory
        ext = (".srt", ".txt")
        contains_other_ext=0
        for file in files:
            if not file.endswith(ext):  
                contains_other_ext=True
        if contains_other_ext== 0:
                send2trash(dir)
                print(dir, ": dir deleted")

删除文件夹,如果其大小小于400kb:

def get_tree_size(path):
    """Return total size of files in given path and subdirs."""
    total = 0
    for entry in os.scandir(path):
        if entry.is_dir(follow_symlinks=False):
            total += get_tree_size(entry.path)
        else:
            total += entry.stat(follow_symlinks=False).st_size
    return total


for dir, subdirs, files in os.walk(root):   
    If get_tree_size(dir) < 400000:  # ≈ 400kb
        send2trash(dir)
    print(dir, "dir deleted")

答案 7 :(得分:5)

如果您确定,要删除整个目录树,并且对dir的内容不再感兴趣,那么对整个目录树进行爬行就是愚蠢...只需从python调用本机OS命令即可。它将更快,更高效,更少内存消耗。

RMDIR c:\blah /s /q 

或* nix

rm -rf /home/whatever 

在python中,代码看起来像..

import sys
import os

mswindows = (sys.platform == "win32")

def getstatusoutput(cmd):
    """Return (status, output) of executing cmd in a shell."""
    if not mswindows:
        return commands.getstatusoutput(cmd)
    pipe = os.popen(cmd + ' 2>&1', 'r')
    text = pipe.read()
    sts = pipe.close()
    if sts is None: sts = 0
    if text[-1:] == '\n': text = text[:-1]
    return sts, text


def deleteDir(path):
    """deletes the path entirely"""
    if mswindows: 
        cmd = "RMDIR "+ path +" /s /q"
    else:
        cmd = "rm -rf "+path
    result = getstatusoutput(cmd)
    if(result[0]!=0):
        raise RuntimeError(result[1])

答案 8 :(得分:4)

根据kkubasik的回答,在删除之前检查文件夹是否存在,更健壮

import shutil
def remove_folder(path):
    # check if folder exists
    if os.path.exists(path):
         # remove if exists
         shutil.rmtree(path)
    else:
         # throw your exception to handle this special scenario
         raise XXError("your exception") 
remove_folder("/folder_name")

答案 9 :(得分:3)

如果您不想使用shutil模块,可以使用os模块。

from os import listdir, rmdir, remove
for i in listdir(directoryToRemove):
    os.remove(os.path.join(directoryToRemove, i))
rmdir(directoryToRemove) # Now the directory is empty of files

答案 10 :(得分:2)

为简单起见,您可以使用os.system命令:

import os
os.system("rm -rf dirname")

很明显,它实际上调用系统终端来完成这项任务。

答案 11 :(得分:2)

def deleteDir(dirPath):
    deleteFiles = []
    deleteDirs = []
    for root, dirs, files in os.walk(dirPath):
        for f in files:
            deleteFiles.append(os.path.join(root, f))
        for d in dirs:
            deleteDirs.append(os.path.join(root, d))
    for f in deleteFiles:
        os.remove(f)
    for d in deleteDirs:
        os.rmdir(d)
    os.rmdir(dirPath)

答案 12 :(得分:1)

删除文件夹即使它可能不存在(避免Charles Chow's answer中的竞争条件)但在其他事情出错时仍然有错误(例如权限问题,磁盘读取错误,该文件不是目录)

对于Python 3.x:

import shutil

def ignore_absent_file(func, path, exc_inf):
    except_instance = exc_inf[1]
    if isinstance(except_instance, FileNotFoundError):
        return
    raise except_instance

shutil.rmtree(dir_to_delete, onerror=ignore_absent_file)

Python 2.7代码几乎相同:

import shutil
import errno

def ignore_absent_file(func, path, exc_inf):
    except_instance = exc_inf[1]
    if isinstance(except_instance, OSError) and \
        except_instance.errno == errno.ENOENT:
        return
    raise except_instance

shutil.rmtree(dir_to_delete, onerror=ignore_absent_file)

答案 13 :(得分:1)

对于os.walk,我将提出由3个单行Python调用组成的解决方案:

python -c "import sys; import os; [os.chmod(os.path.join(rs,d), 0o777) for rs,ds,fs in os.walk(_path_) for d in ds]"
python -c "import sys; import os; [os.chmod(os.path.join(rs,f), 0o777) for rs,ds,fs in os.walk(_path_) for f in fs]"
python -c "import os; import shutil; shutil.rmtree(_path_, ignore_errors=False)"

第一个脚本chmod的所有子目录,第二个脚本chmod的所有文件。然后,第三个脚本将无障碍地删除所有内容。

我已经在Jenkins作业中的“ Shell脚本”中对此进行了测试(我不想将新的Python脚本存储到SCM中,这就是为什么要搜索单行解决方案的原因),并且它适用于Linux和Windows。 / p>

答案 14 :(得分:1)

十年后,使用Python 3.7和Linux仍然有不同的方法:

import subprocess
from pathlib import Path

#using pathlib.Path
path = Path('/path/to/your/dir')
subprocess.run(["rm", "-rf", str(path)])

#using strings
path = "/path/to/your/dir"
subprocess.run(["rm", "-rf", path])

基本上,它使用的是Python的子进程模块来运行bash脚本$ rm -rf '/path/to/your/dir,就像您使用终端来完成相同的任务一样。它不是完全Python,但是可以完成。

之所以加入pathlib.Path示例是因为根据我的经验,当处理许多变化的路径时,它非常有用。对于开发时间来说,导入pathlib.Path模块并将最终结果转换为字符串的额外步骤通常对我来说成本较低。如果Path.rmdir()带有arg选项来显式处理非空dirs,将会很方便。

答案 15 :(得分:0)

我找到了一种非常简单的方法来删除 WINDOWS OS 上的任何文件夹(甚至不是空的)或文件。

X|blnk_1|blnk_2|blnk_3|blnk_4|time1|time2|blnk_5|blnk_6|blnk_7|blnk_8| 
Z01|Str1|01|001|NE]|[HEX1|HEX2]|[NA|001:1000|123:456|[00]|]
Z01|Str2|02|002|NE]|[HEX3|HEX4]|[NA|002:1001|234:456|[01]|]
Z02|02|z2|Str|Str|

答案 16 :(得分:0)

对于Windows,如果目录不为空,并且您具有只读文件,或者出现类似

的错误
  • Access is denied
  • The process cannot access the file because it is being used by another process

尝试一下,os.system('rmdir /S /Q "{}"'.format(directory))

相当于Linux / Mac中的rm -rf

答案 17 :(得分:0)

我想添加一个“纯路径库”方法:

from pathlib import Path
from typing import Union

def del_dir(target: Union[Path, str], only_if_empty: bool = False):
    target = Path(target).expanduser()
    assert target.is_dir()
    for p in sorted(target.glob('**/*'), reverse=True):
        if not p.exists():
            continue
        if p.is_dir():
            p.chmod(0o666)
            p.rmdir()
        else:
            if only_if_empty:
                raise RuntimeError(f'{p.parent} is not empty!')
            p.chmod(0o666)
            p.unlink()
    target.rmdir()

这取决于Path是可排序的事实,较长的路径将始终排在较短的路径之后,就像str一样。因此,目录将位于文件之前。如果我们 反向 进行排序,那么文件将位于它们各自的容器之前,因此我们可以简单地一遍一遍地取消链接/ rmdir它们。

好处:

  • 它不依赖于外部二进制文件:一切都使用Python的电池模块(Python> = 3.6)
  • 速度快且内存效率高:无需递归堆栈,无需启动子进程
  • 这是跨平台的(至少,pathlib在Python 3.6中是这样承诺的;以上所述的任何操作都不能在Windows上运行)
  • 如果需要,可以进行非常精细的日志记录,例如,记录每次删除的发生情况。

答案 18 :(得分:0)

在我的情况下,唯一的删除方法是利用所有可能性,因为我的代码应该由cmd.exe或powershell.exe运行。如果是这种情况,只需使用以下代码创建一个函数,就可以了:

        #!/usr/bin/env python3

        import shutil
        from os import path, system
        import sys

        # Try to delete the folder ---------------------------------------------
        if (path.isdir(folder)):
            shutil.rmtree(folder, ignore_errors=True)

        if (path.isdir(folder)):
            try:
                system("rd -r {0}".format(folder))
            except Exception as e:
                print("WARN: Failed to delete => {0}".format(e),file=sys.stderr)

        if (path.isdir(self.backup_folder_wrk)):
            try:
                system("rd /s /q {0}".format(folder))
            except Exception as e:
                print("WARN: Failed to delete => {0}".format(e),file=sys.stderr)

        if (path.isdir(folder)):
            print("WARN: Failed to delete {0}".format(folder),file=sys.stderr)
        # -------------------------------------------------------------------------------------

答案 19 :(得分:0)

基于递归的纯pathlib解决方案:

from pathlib import Path

def remove_path(path: Path):
    if path.is_file() or path.is_symlink():
        path.unlink()
        return
    for p in path.iterdir():
        remove_path(p)
    path.rmdir()

支持Windows和符号链接