问题:如何删除/删除不为空的文件夹?
尝试删除不为空的文件夹时,出现“访问被拒绝”错误。我尝试使用以下命令:os.remove("/folder_name")
。
删除/删除不为空的文件夹/目录的最有效方法是什么?
I am getting an ‘access is denied’ error when I attempt to delete a folder that is not empty. I used the following command in my attempt: os.remove("/folder_name")
.
What is the most effective way of removing/deleting a folder/directory that is not empty?
回答 0
import shutil
shutil.rmtree('/folder_name')
标准库参考:shutil.rmtree。
根据设计,rmtree
在包含只读文件的文件夹树上失败。如果要删除该文件夹而不管它是否包含只读文件,请使用
shutil.rmtree('/folder_name', ignore_errors=True)
import shutil
shutil.rmtree('/folder_name')
Standard Library Reference: shutil.rmtree.
By design, rmtree
fails on folder trees containing read-only files. If you want the folder to be deleted regardless of whether it contains read-only files, then use
shutil.rmtree('/folder_name', ignore_errors=True)
回答 1
从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 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))
From the python docs on 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 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
import shutil
shutil.rmtree(dest, ignore_errors=True)
import shutil
shutil.rmtree(dest, ignore_errors=True)
回答 3
从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
这里pth
是一个pathlib.Path
实例。不错,但可能不是最快的。
from python 3.4 you may use :
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
where pth
is a pathlib.Path
instance. Nice, but may not be the fastest.
回答 4
来自docs.python.org:
本示例说明如何在Windows上删除目录树,其中某些文件的只读位已设置。它使用onerror回调清除只读位并重新尝试删除。任何后续故障都将传播。
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)
From docs.python.org:
This example shows how to remove a directory tree on Windows where some of the files have their read-only bit set. It uses the onerror callback to clear the readonly bit and reattempt the remove. Any subsequent failure will propagate.
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)
回答 5
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,则将使用参数(函数,路径,exc_info)来处理错误,其中func为os.listdir,os.remove或os.rmdir;path是导致该函数失败的参数。而exc_info是sys.exc_info()返回的元组。如果ignore_errors为false并且onerror为None,则会引发异常。在此处输入代码
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)
If ignore_errors is set, errors are ignored; otherwise, if onerror is set, it is called to handle the error with arguments (func, path, exc_info) where func is os.listdir, os.remove, or os.rmdir; path is the argument to that function that caused it to fail; and exc_info is a tuple returned by sys.exc_info(). If ignore_errors is false and onerror is None, an exception is raised.enter code here
回答 6
根据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")
Base on kkubasik’s answer, check if folder exists before remove, more robust
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")
回答 7
如果您确定要删除整个目录树,并且不再对目录内容感兴趣,那么爬网整个目录树是愚蠢的……只需从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])
if you are sure, that you want to delete the entire dir tree, and are no more interested in contents of dir, then crawling for entire dir tree is stupidness… just call native OS command from python to do that. It will be faster, efficient and less memory consuming.
RMDIR c:\blah /s /q
or *nix
rm -rf /home/whatever
In python, the code will look like..
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
只需一些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")
Just some python 3.5 options to complete the answers above. (I would have loved to find them here).
import os
import shutil
from send2trash import send2trash # (shutil delete permanently)
Delete folder if empty
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")
Delete also folder if it contains this file
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)
delete folder if it contains only .srt or .txt file(s)
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")
Delete folder if its size is less than 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")
回答 9
我想添加“纯路径库”方法:
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
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上运行) - 如果需要,可以进行非常精细的日志记录,例如,记录每次删除的发生。
I’d like to add a “pure pathlib” approach:
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
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()
This relies on the fact that Path
is orderable, and longer paths will always sort after shorter paths, just like str
. Therefore, directories will come before files. If we reverse the sort, files will then come before their respective containers, so we can simply unlink/rmdir them one by one with one pass.
Benefits:
- It’s NOT relying on external binaries: everything uses Python’s batteries-included modules (Python >= 3.6)
- It’s fast and memory-efficient: No recursion stack, no need to start a subprocess
- It’s cross-platform (at least, that’s what
pathlib
promises in Python 3.6; no operation above stated to not run on Windows) - If needed, one can do a very granular logging, e.g., log each deletion as it happens.
回答 10
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)
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)
回答 11
如果您不想使用该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
If you don’t want to use the shutil
module you can just use the os
module.
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
回答 12
十年后,使用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 ,将很方便。
Ten years later and using Python 3.7 and Linux there are still different ways to do this:
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])
Essentially it’s using Python’s subprocess module to run the bash script $ rm -rf '/path/to/your/dir
as if you were using the terminal to accomplish the same task. It’s not fully Python, but it gets it done.
The reason I included the pathlib.Path
example is because in my experience it’s very useful when dealing with many paths that change. The extra steps of importing the pathlib.Path
module and converting the end results to strings is often a lower cost to me for development time. It would be convenient if Path.rmdir()
came with an arg option to explicitly handle non-empty dirs.
回答 13
即使一个文件夹可能不存在,也要删除该文件夹(避免使用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)
To delete a folder even if it might not exist (avoiding the race condition in Charles Chow’s answer) but still have errors when other things go wrong (e.g. permission problems, disk read error, the file isn’t a directory)
For 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)
The Python 2.7 code is almost the same:
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)
回答 14
使用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。
With os.walk I would propose the solution which consists of 3 one-liner Python calls:
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)"
The first script chmod’s all sub-directories, the second script chmod’s all files. Then the third script removes everything with no impediments.
I have tested this from the “Shell Script” in a Jenkins job (I did not want to store a new Python script into SCM, that’s why searched for a one-line solution) and it worked for Linux and Windows.
回答 15
为了简单起见,可以使用os.system命令:
import os
os.system("rm -rf dirname")
显而易见,它实际上调用系统终端来完成此任务。
You can use os.system command for simplicity:
import os
os.system("rm -rf dirname")
As obvious, it actually invokes system terminal to accomplish this task.
回答 16
我发现一种非常简单的方法来删除WINDOWS OS上的任何文件夹(甚至不为空)或文件。
os.system('powershell.exe rmdir -r D:\workspace\Branches\*%s* -Force' %CANDIDATE_BRANCH)
I have found a very easy way to Delete any folder(Even NOT Empty) or file on WINDOWS OS.
os.system('powershell.exe rmdir -r D:\workspace\Branches\*%s* -Force' %CANDIDATE_BRANCH)
回答 17
对于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))
rm -rf
在Linux / Mac中等效。
For Windows, if directory is not empty, and you have read-only files or you get errors like
Access is denied
The process cannot access the file because it is being used by another process
Try this, os.system('rmdir /S /Q "{}"'.format(directory))
It’s equivalent for rm -rf
in Linux/Mac.
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。