当我试图删除一个非空文件夹时,我得到一个“访问被拒绝”错误。我在尝试中使用了以下命令:os.remove("/folder_name")。
删除一个非空文件夹/目录最有效的方法是什么?
当我试图删除一个非空文件夹时,我得到一个“访问被拒绝”错误。我在尝试中使用了以下命令:os.remove("/folder_name")。
删除一个非空文件夹/目录最有效的方法是什么?
当前回答
删除一个文件夹,即使它可能不存在(避免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):
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)
其他回答
来自os.walk()的python文档:
# 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))
我想添加一个“纯pathlib”方法:
from pathlib import Path
from 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():
continue
p.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上运行) 如果需要,可以进行非常细粒度的日志记录,例如,记录每一次删除。
十年后,在使用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的原因。路径示例是因为根据我的经验,它在处理许多路径变化时非常有用。导入pathlib的额外步骤。路径模块和将最终结果转换为字符串通常是一个较低的成本,我的开发时间。如果Path.rmdir()带有一个arg选项来显式地处理非空dirs,那就很方便了。
在我的情况下,删除的唯一方法是使用所有的可能性,因为我的代码应该运行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)
# -------------------------------------------------------------------------------------
如果你确定你想要删除整个目录树,并且不再对目录的内容感兴趣,那么爬行整个目录树是愚蠢的…只需从python中调用本机操作系统命令即可。它将更快,更有效,更少的内存消耗。
RMDIR c:\blah /s /q
例如*那晚尼克斯。
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])