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

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

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

904777 次浏览
import shutil
shutil.rmtree('/folder_name')

标准库参考:shutil.rmtree

根据设计,rmtree在包含只读文件的文件夹树上失败。如果您希望删除该文件夹,而不管它是否包含只读文件,请使用

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

的python文档os.walk()

# 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 osfor 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))

如果您确定要删除整个dir树,并且对dir的内容不再感兴趣,那么爬取整个dir树是愚蠢的……只需从python调用本机操作系统命令即可。它会更快、更高效、更少内存消耗。

RMDIR c:\blah /s /q

或*nix

rm -rf /home/whatever

在python中,代码看起来像…

import sysimport 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 = 0if 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 "+pathresult = getstatusoutput(cmd)if(result[0]!=0):raise RuntimeError(result[1])
import shutilshutil.rmtree(dest, ignore_errors=True)
import osimport statimport 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: 0777os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)# retryfunc(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为无,则此处raised.enter代码出现异常

在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 the dir content but not the dir itself, remove this line

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

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

import shutildef remove_folder(path):# check if folder existsif os.path.exists(path):# remove if existsshutil.rmtree(path)else:# throw your exception to handle this special scenarioraise XXError("your exception")remove_folder("/folder_name")

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

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

显然,它实际上调用系统终端来完成此任务。

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

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

只是一些python 3.5选项来完成上面的答案。(我很想在这里找到它们)。

import osimport shutilfrom 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 fileif files[0]== "desktop.ini" or:send2trash(dir)print(dir, ": folder removed")else:print(dir)

删除仅包含. srt或. txt文件的文件夹

    elif subdirs == []: #if dir doesn’t contains subdirectoryext = (".srt", ".txt")contains_other_ext=0for file in files:if not file.endswith(ext):contains_other_ext=Trueif 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 = 0for 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_sizereturn total

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

docs.python.org

此示例显示如何在Windows上删除目录树一些文件设置了只读位。它使用on错误回调以清除只读位并重新尝试删除。任何随后的故障会传播。

import os, statimport 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)

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

对于Python 3. x:

import shutil
def ignore_absent_file(func, path, exc_inf):except_instance = exc_inf[1]if isinstance(except_instance, FileNotFoundError):returnraise except_instance
shutil.rmtree(dir_to_delete, onerror=ignore_absent_file)

Python 2.7代码几乎相同:

import shutilimport 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:returnraise except_instance
shutil.rmtree(dir_to_delete, onerror=ignore_absent_file)
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)

我找到了一个非常简单的方法来删除任何文件夹(即使不是空的)windows操作系统上的文件。

os.system('powershell.exe  rmdir -r D:\workspace\Branches\*%s* -Force' %CANDIDATE_BRANCH)

使用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。

十年后,使用Python 3.7和Linux仍然有不同的方法来做到这一点:

import subprocessfrom pathlib import Path
#using pathlib.Pathpath = Path('/path/to/your/dir')subprocess.run(["rm", "-rf", str(path)])
#using stringspath = "/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会很方便。

对于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中的rm -rf /Mac.

我想添加一个“纯Pathlib”方法:

from pathlib import Pathfrom typing import Union
def del_dir(target: Union[Path, str], only_if_empty: bool = False):"""Delete a given directory and its subdirectories.
:param target: The directory to delete:param only_if_empty: Raise RuntimeError if any file is found in the tree"""target = Path(target).expanduser()assert target.is_dir()for p in sorted(target.glob('**/*'), reverse=True):if not p.exists():continuep.chmod(0o666)if p.is_dir():p.rmdir()else:if only_if_empty:raise RuntimeError(f'{p.parent} is not empty!')p.unlink()target.rmdir()

这依赖于Path是可排序的事实,更长的路径总是在更短的路径之后排序,就像str一样。因此,目录将排在文件之前。如果我们反转排序,文件将排在它们各自的容器之前,所以我们可以简单地通过一个通道一个接一个地解除关联/rmdir。

好处:

  • 它不依赖于外部二进制文件:一切都使用Python的电池模块(Python>=3.6)
    • 这意味着它不需要重复启动一个新的子进程来进行取消链接
  • 它非常快速和简单;您不必实现自己的递归
  • 它是跨平台的(至少,这是pathlib在Python 3.6中承诺的;上面没有说明不能在Windows上运行的操作)
  • 如果需要,可以进行非常细粒度的日志记录,例如,记录每次删除。

在我的情况下,删除的唯一方法是使用所有的可能性,因为我的代码应该由cmd.exe或powershell.exe.如果是您的情况,只需使用此代码创建一个函数,您就会没事:

        #!/usr/bin/env python3
import shutilfrom os import path, systemimport 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)# -------------------------------------------------------------------------------------

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

from pathlib import Path
def remove_path(path: Path):if path.is_file() or path.is_symlink():path.unlink()returnfor p in path.iterdir():remove_path(p)path.rmdir()

支持Windows和符号链接

您可以尝试下面的代码来删除文件或文件夹,无论它们是空的还是非空的。

import shutilimport os
directory = "path/to/the/root/folder"files_in_directory = os.listdir(directory)
for file in files_in_directory:try:path_to_file_or_folder = os.path.join(directory, file)shutil.rmtree(path_to_file_or_folder)except:os.unlink(path_to_file_or_folder)

它有助于删除包含所有文件和文件夹的目录

import os

def rrmdir(path):for entry in os.scandir(path):if entry.is_dir():rrmdir(entry)else:os.remove(entry)os.rmdir(path)