如何删除文件夹的内容?
Posted
技术标签:
【中文标题】如何删除文件夹的内容?【英文标题】:How to delete the contents of a folder? 【发布时间】:2010-09-16 04:51:21 【问题描述】:如何在 Python 中删除本地文件夹的内容?
当前项目是针对 Windows 的,但我也想看看 *nix。
【问题讨论】:
对于 *nix,老实说我只会使用os.system('rm -rf folder')
【参考方案1】:
import os, shutil
folder = '/path/to/folder'
for filename in os.listdir(folder):
file_path = os.path.join(folder, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
except Exception as e:
print('Failed to delete %s. Reason: %s' % (file_path, e))
【讨论】:
如果您正在处理一个非常大的目录,尤其是 Windows 上的网络目录,并且您可以控制该程序运行的环境,那么可能值得使用 Py3.5 的“os. scandir(folder)" 函数而不是 listdir。之后的语法完全不同,但实现起来非常简单;如果其他人愿意,很乐意发布。 我收到except Exception as e:
的pylint 警告,内容为W0703: Catching too general exception Exception
。是否有更具体的异常要捕获还是应该忽略它?
@JohnHany,我相信你想捕捉 OSError。
我收到 OSError: [Errno 26] Text file busy My file structure: Media(like folder in your code) contains->2 个文件和 2 个目录,其中两个目录都包含一个文件跨度>
【参考方案2】:
你最好使用os.walk()
来做这个。
os.listdir()
不区分文件和目录,你很快就会在试图取消链接时遇到麻烦。有一个使用os.walk()
递归删除目录here 的好例子,并提示如何根据您的情况调整它。
【讨论】:
【参考方案3】:您可以使用shutil.rmtree
删除文件夹本身及其所有内容:
import shutil
shutil.rmtree('/path/to/folder')
shutil.<b>rmtree</b>(<i>path</i>, <i>ignore_errors=False</i>, <i>onerror=None</i>)
删除整个目录树; path 必须指向一个目录(但不是指向目录的符号链接)。如果 ignore_errors 为真,则删除失败导致的错误将被忽略;如果为 false 或省略,则通过调用 onerror 指定的处理程序来处理此类错误,如果省略,则引发异常。
【讨论】:
这不仅会删除内容,还会删除文件夹本身。我不认为这是问题所要问的。 因为新目录和旧目录不一样。因此,如果一个程序位于目录中,等待某些事情,它就会从它下面拉出地毯。 只需在rmtree
之后重新创建目录即可。喜欢os.makedirs(dir)
@IuliusCurt 不,我有一个安装在 ram 中的目录我需要清空,不幸的是我不能删除然后重新创建它:OSError: [Errno 16] Device or resource busy
你必须注意重新创建文件夹不一定相同,例如如果你将文件夹挂载到docker并删除文件夹,在docker内重新创建文件夹不会导致重新创建挂载的文件夹.【参考方案4】:
扩展 mhawke 的答案,这就是我已经实现的。它会删除文件夹的所有内容,但不会删除文件夹本身。在 Linux 上使用文件、文件夹和符号链接进行测试,应该也可以在 Windows 上运行。
import os
import shutil
for root, dirs, files in os.walk('/path/to/folder'):
for f in files:
os.unlink(os.path.join(root, f))
for d in dirs:
shutil.rmtree(os.path.join(root, d))
【讨论】:
为什么要“走”而不只是列出文件夹内容? 如果您也想删除目录,这是正确的答案。walk
用于拆分目录与文件,必须以不同方式处理。您也可以使用os.listdir
,但您必须手动检查每个条目是目录还是文件。
这很接近,但 os.walk 和 shutil.rmtree 都是递归的。 os.walk 是不必要的,因为您只需要清理目录内顶层的文件和目录。只需对 os.listdir 中的元素使用 if 语句来查看每个元素是文件还是目录。然后分别使用remove/unlink和rmtree。
@MatthewAlpert 但是请注意,os.walk
不会在这里递归,因为它会返回一个生成器,当您尝试推进它时,它只会递归地查看子目录,并且当您完成时这个循环的第一次迭代,没有子目录可供查看。本质上,os.walk
只是在这里用作区分***文件夹和***文件的另一种方式;没有使用递归,我们不为此付出任何性能成本。不过,这很古怪,我同意你建议的方法更好,因为它更明确、更易读。【参考方案5】:
你可以这样做:
import os
import glob
files = glob.glob('/YOUR/PATH/*')
for f in files:
os.remove(f)
您当然可以在路径中使用其他过滤器,例如:/YOU/PATH/*.txt 用于删除目录中的所有文本文件。
【讨论】:
@Blueicefield*
不会列出隐藏文件,我们还要加上glob.glob('path/.*)
虽然要删除文件列表,但对我来说似乎更简单:import sh; sh.rm(files)
虽然import sh; sh.rm(files)
看起来更漂亮,但如果目录中的文件超过 1024 个,您就会遇到麻烦。
@satoru 你将如何添加这个隐藏文件的其他通配符?
子目录抛出异常【参考方案6】:
使用rmtree
并重新创建文件夹可以工作,但在删除并立即重新创建网络驱动器上的文件夹时遇到错误。
使用 walk 的建议解决方案不起作用,因为它使用 rmtree
删除文件夹,然后可能会尝试对之前位于这些文件夹中的文件使用 os.unlink
。这会导致错误。
发布的glob
解决方案也会尝试删除非空文件夹,导致错误。
我建议你使用:
folder_path = '/path/to/folder'
for file_object in os.listdir(folder_path):
file_object_path = os.path.join(folder_path, file_object)
if os.path.isfile(file_object_path) or os.path.islink(file_object_path):
os.unlink(file_object_path)
else:
shutil.rmtree(file_object_path)
【讨论】:
如果存在指向其他目录的符号链接,您的解决方案也会引发错误。 @Blueicefield - 你能举个例子吗?我已经在 linux 中使用符号链接的文件和文件夹进行了测试,但还没有导致错误。 @jgoeders - 如果有指向目录的符号链接,os.path.isfile()
将返回 False
(因为它遵循符号链接),您最终会在符号链接上调用 shutil.rmtree()
,这将提高OSError("Cannot call rmtree on a symbolic link")
.
@Rockallite 通过检查 islink 修复
另外:@kevinf 指出需要在此处检查 islink
以正确处理指向目录的符号链接是正确的。我已经在接受的答案中添加了这样的检查。【参考方案7】:
这个:
删除所有符号链接 死链接 目录链接 文件链接 删除子目录 不删除父目录代码:
for filename in os.listdir(dirpath):
filepath = os.path.join(dirpath, filename)
try:
shutil.rmtree(filepath)
except OSError:
os.remove(filepath)
与许多其他答案一样,这不会尝试调整权限以启用文件/目录的删除。
【讨论】:
【参考方案8】:在 Python 3.6+ 中使用 os.scandir and context manager protocol:
import os
import shutil
with os.scandir(target_dir) as entries:
for entry in entries:
if entry.is_dir() and not entry.is_symlink():
shutil.rmtree(entry.path)
else:
os.remove(entry.path)
早期版本的 Python:
import os
import shutil
# Gather directory contents
contents = [os.path.join(target_dir, i) for i in os.listdir(target_dir)]
# Iterate and remove each item in the appropriate manner
[shutil.rmtree(i) if os.path.isdir(i) and not os.path.islink(i) else os.remove(i) for i in contents]
【讨论】:
os.path.isdir()
不是区分常规目录和符号链接的有效方法。在符号链接上调用 shutil.rmtree()
将引发 OSError
异常。
@Rockallite 谢谢。你说得对。我更新了示例。
你不应该需要is_file()
:至少在 Unix 上,用于删除特殊文件的底层系统调用与常规文件相同 - unlink。只有真正的目录需要递归处理,即is_dir() and not is_symlink()
(为了正确处理目录的符号链接,就像你已经做的那样)。
谢谢,@user2394284。我根据您的反馈更新了示例。【参考方案9】:
我知道这是一个旧线程,但我从 python 的官方站点发现了一些有趣的东西。只是为了分享另一个删除目录中所有内容的想法。因为我在使用 shutil.rmtree() 时遇到了一些授权问题,我不想删除目录并重新创建它。地址原为http://docs.python.org/2/library/os.html#os.walk。希望这可以帮助某人。
def emptydir(top):
if(top == '/' or top == "\\"): return
else:
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))
【讨论】:
【参考方案10】:我以前是这样解决问题的:
import shutil
import os
shutil.rmtree(dirpath)
os.mkdir(dirpath)
【讨论】:
这与问题提出的语义完全不同,不应被视为有效答案。 不理解您的评论:>“如何在 Python 中删除本地文件夹的内容。当前项目适用于 Windows,但我也希望看到 *nix。”是问题.答案解决了任务。 这就像回答“如何让函数在 Python 中返回数字 1?”这个问题。 with def return_a_one(): launch_some_nukes() return 1 当然语义不同:但您不妨将其视为看待问题的另一种方式。该解决方案完全有效,因为它解决了问题。您的“launch_some_nukes”示例有所不同:1.该解决方案比公认的解决方案更短,更容易,并且与您引用的答案相反,它是有效的。 2. 在这种情况下,'launch_some_nukes' 等效项是删除并重新创建一个文件夹。新旧文件夹的区别只是inode号(可能与OP无关) 倒是拆掉摩天大楼,重新建一个大小一模一样的摩天大楼;)【参考方案11】:作为单行者:
import os
# Python 2.7
map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
# Python 3+
list( map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) ) )
考虑文件和目录的更强大的解决方案是 (2.7):
def rm(f):
if os.path.isdir(f): return os.rmdir(f)
if os.path.isfile(f): return os.unlink(f)
raise TypeError, 'must be either file or directory'
map( rm, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
【讨论】:
对于使用生成器的大型操作可能会更高效map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
实际上尝试使用它,意识到必须迭代地图对象,因此需要调用列表(或将迭代的东西),如list(map(os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir))))
第一个包含在答案中,第二个对我来说毫无意义。为什么要遍历映射到可迭代对象的函数?地图就是这样做的。
在 Python3 中,您必须将 map
包裹在 list
中才能真正进行迭代。见http://***.com/questions/1303347/getting-a-map-to-return-a-list-in-python-3-x
如果 'mydir' 包含至少一个文件夹,这个绝对不会起作用,因为 unlink 仅适用于文件...【参考方案12】:
另一个解决方案:
import sh
sh.rm(sh.glob('/path/to/folder/*'))
【讨论】:
请注意,sh
不是标准库的一部分,需要先从 PyPI 安装,然后才能使用它。此外,由于这实际上在子进程中调用了rm
,因此它不适用于不存在rm
的Windows。如果文件夹包含任何子目录,它也会引发异常。【参考方案13】:
注意:如果有人对我的答案投了反对票,我在这里有一些事情要解释。
-
每个人都喜欢简短的“n”简单答案。然而,有时现实并非如此简单。
回到我的答案。我知道
shutil.rmtree()
可以用来删除目录树。我在自己的项目中多次使用它。但是你必须意识到目录本身也会被shutil.rmtree()
删除。虽然这对某些人来说可能是可以接受的,但对于删除文件夹的内容(没有副作用)来说,这不是一个有效的答案。
我将向您展示一个副作用示例。假设您有一个包含 customized 所有者和模式位的目录,其中有很多内容。然后用shutil.rmtree()
删除它并用os.mkdir()
重建它。您将获得一个带有 default (继承的)所有者和模式位的空目录。虽然您可能有权删除内容甚至目录,但您可能无法设置目录的原始所有者和模式位(例如,您不是超级用户)。
最后,耐心阅读代码。它又长又丑(看得见),但被证明是可靠和高效的(在使用中)。
这是一个冗长而丑陋但可靠且高效的解决方案。
它解决了其他回答者没有解决的一些问题:
它正确处理符号链接,包括不在符号链接上调用shutil.rmtree()
(如果它链接到目录,它将通过os.path.isdir()
测试;即使os.walk()
的结果也包含符号链接目录)。
它可以很好地处理只读文件。
这是代码(唯一有用的函数是clear_dir()
):
import os
import stat
import shutil
# http://***.com/questions/1889597/deleting-directory-in-python
def _remove_readonly(fn, path_, excinfo):
# Handle read-only files and directories
if fn is os.rmdir:
os.chmod(path_, stat.S_IWRITE)
os.rmdir(path_)
elif fn is os.remove:
os.lchmod(path_, stat.S_IWRITE)
os.remove(path_)
def force_remove_file_or_symlink(path_):
try:
os.remove(path_)
except OSError:
os.lchmod(path_, stat.S_IWRITE)
os.remove(path_)
# Code from shutil.rmtree()
def is_regular_dir(path_):
try:
mode = os.lstat(path_).st_mode
except os.error:
mode = 0
return stat.S_ISDIR(mode)
def clear_dir(path_):
if is_regular_dir(path_):
# Given path is a directory, clear its content
for name in os.listdir(path_):
fullpath = os.path.join(path_, name)
if is_regular_dir(fullpath):
shutil.rmtree(fullpath, onerror=_remove_readonly)
else:
force_remove_file_or_symlink(fullpath)
else:
# Given path is a file or a symlink.
# Raise an exception here to avoid accidentally clearing the content
# of a symbolic linked directory.
raise OSError("Cannot call clear_dir() on a symbolic link")
【讨论】:
我不明白在什么情况下更改文件模式是有意义的。在我的 Mac 上,os.remove
不像rm
实用程序很乐意删除只读文件,只要您拥有它们。同时,如果它是您不拥有且您只有只读访问权限的文件,则您不能删除它或更改其权限。我不知道在任何系统上您无法使用os.remove
删除只读文件但能够更改其权限的任何情况。此外,您使用lchmod
,根据其文档,它在我的 Mac 和 Windows 上都不存在。这段代码适用于什么平台?!【参考方案14】:
这应该只是使用操作系统模块列出然后删除!
import os
DIR = os.list('Folder')
for i in range(len(DIR)):
os.remove('Folder'+chr(92)+i)
为我工作,有任何问题请告诉我!
【讨论】:
【参考方案15】:针对有限的特定情况的答案: 假设您想在维护子文件夹树的同时删除文件,您可以使用递归算法:
import os
def recursively_remove_files(f):
if os.path.isfile(f):
os.unlink(f)
elif os.path.isdir(f):
for fi in os.listdir(f):
recursively_remove_files(os.path.join(f, fi))
recursively_remove_files(my_directory)
也许有点离题,但我想很多人会觉得它很有用
【讨论】:
以***.com/a/54889532/1709587 所示的方式使用os.walk
可能是删除所有文件同时保持目录结构完整的更好方法。【参考方案16】:
我通过在rmtree
makedirs
之间添加time.sleep()
解决了这个问题:
if os.path.isdir(folder_location):
shutil.rmtree(folder_location)
time.sleep(.5)
os.makedirs(folder_location, 0o777)
【讨论】:
【参考方案17】:如果您使用的是 *nix 系统,为什么不利用 system 命令?
import os
path = 'folder/to/clean'
os.system('rm -rf %s/*' % path)
【讨论】:
因为,如问题中所述,“当前项目适用于 Windows” @soxwithMonica 这个命令不能适应 Windows 终端语法吗? @Jivan 当然可以。 哎呀。使用 -rf 运行很危险。如果路径有错误...最终可能会删除重要文件。os.system
+ 字符串处理 + 不正确的引用 = shell 注入【参考方案18】:
使用下面的方法删除目录的内容,而不是目录本身:
import os
import shutil
def remove_contents(path):
for c in os.listdir(path):
full_path = os.path.join(path, c)
if os.path.isfile(full_path):
os.remove(full_path)
else:
shutil.rmtree(full_path)
【讨论】:
@Fabiospaghetti 否定 谢谢阿米尔,我正在寻找一种解决方案,可以在根目录的所有子目录中找到某个文件夹并删除该文件夹的内容 这不会增加您发布此内容之前几年已接受的答案中未显示的新内容。【参考方案19】:要删除目录及其子目录中的所有文件,而不删除文件夹本身,只需执行以下操作:
import os
mypath = "my_folder" #Enter your path here
for root, dirs, files in os.walk(mypath):
for file in files:
os.remove(os.path.join(root, file))
【讨论】:
【参考方案20】:我很惊讶没有人提到很棒的 pathlib
来完成这项工作。
如果你只想删除目录中的文件,它可以是一个单行器
from pathlib import Path
[f.unlink() for f in Path("/path/to/folder").glob("*") if f.is_file()]
要递归删除目录,您可以编写如下内容:
from pathlib import Path
from shutil import rmtree
for path in Path("/path/to/folder").glob("**/*"):
if path.is_file():
path.unlink()
elif path.is_dir():
rmtree(path)
【讨论】:
.iterdir()
而不是 .glob(...)
也应该可以工作。【参考方案21】:
非常直观的做法:
import shutil, os
def remove_folder_contents(path):
shutil.rmtree(path)
os.makedirs(path)
remove_folder_contents('/path/to/folder')
【讨论】:
【参考方案22】:删除文件夹中所有文件/删除所有文件的最简单方法
import os
files = os.listdir(yourFilePath)
for f in files:
os.remove(yourFilePath + f)
【讨论】:
如果有子目录则失败。【参考方案23】:嗯,我认为这段代码是有效的。它不会删除文件夹,您可以使用此代码删除具有特定扩展名的文件。
import os
import glob
files = glob.glob(r'path/*')
for items in files:
os.remove(items)
【讨论】:
【参考方案24】:我不得不从单个父目录中的 3 个单独文件夹中删除文件:
directory
folderA
file1
folderB
file2
folderC
file3
这个简单的代码帮了我大忙:(我在 Unix 上)
import os
import glob
folders = glob.glob('./path/to/parentdir/*')
for fo in folders:
file = glob.glob(f'fo/*')
for f in file:
os.remove(f)
希望这会有所帮助。
【讨论】:
【参考方案25】:要删除我使用的文件夹中的所有文件:
import os
for i in os.listdir():
os.remove(i)
【讨论】:
只是强调这仅在给定目录仅包含文件时才有效。如果目录包含另一个目录,则会引发IsADirectoryError
异常。以上是关于如何删除文件夹的内容?的主要内容,如果未能解决你的问题,请参考以下文章