如何删除文件夹的内容?


468

如何在Python中删除本地文件夹的内容?

当前项目适用于Windows,但我也希望看到* nix。


2
* nix说实话,我只会用os.system('rm -rf folder')
Tilak Maddy

Answers:


441
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))

4
如果您使用的是非常大的目录,尤其是Windows上的网络目录,并且可以控制该程序的运行环境,那么使用Py3.5的“ os.scandir(folder)”函数代替listdir。此后的语法是完全不同的,但是实现起来非常简单。如果其他人愿意,很高兴将其发布。
迈克尔·斯科特·库斯伯特

我得到一个警告,pylint的与except Exception as e:读取W0703: Catching too general exception Exception。是否有要捕获的更具体的异常,还是应该忽略它?
约翰·汉尼

7
@JohnHany,我相信您想抓住OSError。
MikeB

245

您可以简单地做到这一点:

import os
import glob

files = glob.glob('/YOUR/PATH/*')
for f in files:
    os.remove(f)

当然,您可以在路径中使用其他过滤器,例如:/YOU/PATH/*.txt,以删除目录中的所有文本文件。


12
@Blueicefield *不会列出隐藏文件,我们还应该添加glob.glob('path/.*)
satoru

5
尽管删除文件列表,对我来说似乎更简单:import sh; sh.rm(files)
Robin Winslow 2014年

2
虽然import sh; sh.rm(files)看起来更漂亮,但是如果目录中有1024个以上的文件,则会遇到麻烦。
尤金

234

您可以使用以下命令删除文件夹本身及其所有内容shutil.rmtree

import shutil
shutil.rmtree('/path/to/folder')
shutil.rmtree(path, ignore_errors=False, onerror=None)


删除整个目录树;路径必须指向目录(但不能指向目录的符号链接)。如果ignore_errors为true,则删除失败导致的错误将被忽略;如果为false或忽略,则通过调用onerror指定的处理程序来处理此类错误;如果省略,则引发异常。


270
这不仅会删除内容,还会删除文件夹本身。我不认为这是问题所在。
Iker Jimenez

3
我认为这是一个很好的答案。为什么不删除内容和文件夹,然后重新制作文件夹呢?
cssndrx 2011年

42
因为新目录和旧目录不会相同。因此,如果程序正坐在目录中等待操作,它将把地毯从其下面拉出。
Mike Cooper

30
只需在之后创建目录rmtree。喜欢os.makedirs(dir)
Iulius Curt

3
@IuliusCurt不,我有一个挂载在ram中的目录,我需要清空,很遗憾,我不能只删除然后重新创建它:OSError: [Errno 16] Device or resource busy
Arnaud P

80

扩展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))

1
为什么要“遍历”而不是仅列出文件夹内容?

2
如果您也要删除目录,这是正确的答案。 walk用于分割目录和文件,必须以不同的方式处理。您也可以使用os.listdir,但是您必须手动检查每个条目是目录还是文件。
dkamins 2012年

7
这很接近,但是os.walk和shutil.rmtree都是递归的。os.walk是不必要的,因为您只需要清除目录内顶层的文件和目录。只需对os.listdir中的元素使用if语句,以查看每个元素是文件还是目录。然后分别使用remove / unlink和rmtree。
马修·阿尔珀特

1
@MatthewAlpert注意,os.walk这里不会递归,因为它返回一个生成器,当您尝试推进它时,它仅以递归方式查看子目录,并且当您完成此循环的第一次迭代时,没有子目录左看。本质上,os.walk这里只是将其用作区分顶级文件夹和顶级文件的另一种方法。没有使用递归,因此我们不为此付出任何性能成本。但是,它很古怪,我同意您建议的方法更好,因为它更明确,更易读。
Mark Amery

47

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

1
如果存在指向其他目录的符号链接,您的解决方案也会引发错误。
Blueicefield

@Blueicefield-您能举个例子吗?我已经在Linux中使用符号链接的文件和文件夹进行了测试,但尚未引起错误。
jgoeders 2014年

@jgoeders-如果目录中有符号链接,os.path.isfile()则将返回False(因为它遵循符号链接),最后您将调用shutil.rmtree()一个符号链接,该符号链接将引发OSError("Cannot call rmtree on a symbolic link")
Rockallite

1
@Rockallite通过检查固定到islink
kevinf

1
另外:@kevinf是正确的,指出需要在islink此处进行检查以正确处理目录的符号链接。我已经在接受的答案中添加了这样的支票。
Mark Amery

20

这个:

  • 删除所有符号链接
    • 无效链接
    • 链接到目录
    • 链接到文件
  • 删除子目录
  • 不删除父目录

码:

for filename in os.listdir(dirpath):
    filepath = os.path.join(dirpath, filename)
    try:
        shutil.rmtree(filepath)
    except OSError:
        os.remove(filepath)

与许多其他答案一样,这不会尝试调整权限以启用文件/目录的删除。


15

作为单线:

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

1
使用发电机进行大型操作的效率可能会高一些map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
user25064 2014年

实际上尝试使用此功能,意识到必须迭代map对象,因此需要调用list(或将要迭代的内容),例如list(map(os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir))))
user25064 2014年

答案中包括第一个,第二个对我来说毫无意义。为什么要遍历映射到Iterable的函数?地图可以做到这一点。
fmonegaglia

1
在Python3中,您必须包装maplist 才能真正进行迭代。参见http://stackoverflow.com/questions/1303347/getting-a-map-to-return-a-list-in-python-3-x
paulwasit

如果'mydir'至少包含一个文件夹,则该文件夹绝对不起作用,因为取消链接仅适用于文件...
kupsef

14

注意:万一有人否决了我的答案,请在此说明。

  1. 每个人都喜欢简短的“ n”个简单答案。但是,有时现实并非如此简单。
  2. 回到我的答案。我知道shutil.rmtree()可以用来删除目录树。我在自己的项目中使用了很多次。但是您必须意识到目录本身也会被删除shutil.rmtree()。尽管这对于某些人来说可能是可以接受的,但这对于删除文件夹的内容不是一个有效的答案(无副作用)
  3. 我会给你一个副作用的例子。假设您有一个包含自定义所有者和模式位的目录,其中包含很多内容。然后,您使用删除它shutil.rmtree()并使用重建它os.mkdir()。然后,您将获得一个空目录,该目录具有默认(继承)的所有者和模式位。尽管您可能有权删除目录甚至目录,但是您可能无法在目录上设置原始所有者和模式位(例如,您不是超级用户)。
  4. 最后,请耐心阅读代码。它长而丑陋(可见),但事实证明是可靠且有效的(使用中)。

这是一个长而丑陋但可靠且有效的解决方案。

它解决了一些其他答复者无法解决的问题:

  • 它可以正确处理符号链接,包括不调用shutil.rmtree()符号链接(os.path.isdir()如果它链接到目录,它将通过测试;甚至结果也os.walk()包含符号链接目录)。
  • 它很好地处理了只读文件。

这是代码(唯一有用的函数是clear_dir()):

import os
import stat
import shutil


# http://stackoverflow.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都不存在。该代码适用于什么平台?
Mark Amery

14

我感到惊讶的是,没有人提到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)

1
.iterdir()而不是也.glob(...)应该工作。
S. Kirby

11
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
[os.remove(i) if os.path.isfile(i) or os.path.islink(i) else shutil.rmtree(i) for i in contents]

较早的注释还提到在Python 3.5+中使用os.scandir。例如:

import os
import shutil

with os.scandir(target_dir) as entries:
    for entry in entries:
        if entry.is_file() or entry.is_symlink():
            os.remove(entry.path)
        elif entry.is_dir():
            shutil.rmtree(entry.path)

1
os.path.isdir()这不是区分常规目录和符号链接的有效方法。调用shutil.rmtree()符号链接将引发OSError异常。
Rockallite

@Rockallite谢谢。你是对的。我更新了示例。
雅各布·万

8

使用os.walk()此功能可能会更好。

os.listdir()不能将文件与目录区分开来,因此您在尝试取消链接时会很快遇到麻烦。有使用的一个很好的例子os.walk()递归删除目录在这里,以及如何使其适应你的情况提示。


6

我曾经通过这种方式解决问题:

import shutil
import os

shutil.rmtree(dirpath)
os.mkdir(dirpath)

7
这与问题所要表达的语义完全不同,因此不应将其视为有效答案。
fatuhoku 2013年

1
相对而言,我认为“删除本地文件夹的内容”并不涉及删除文件夹本身。与这个答案相同的问题,除了一个人有很多支持!
fatuhoku 2013年

3
这就像回答问题“我如何让一个函数在Python中返回数字1”?与def return_a_one():launch_some_nukes()返回1
fatuhoku 2013年

2
当然,语义是不同的:但是您最好将其视为解决问题的另一种方法。此解决方案解决了问题,因此非常有效。您的“ launch_some_nukes”示例与众不同:1.该解决方案比公认的解决方案更短,更容易,并且反对您引用的答案是有效的。2.在这种情况下,等效的“ launch_some_nukes”是删除并重新创建文件夹。新旧文件夹之间的区别只是
索引

2
它是在拆除摩天大楼,然后重建一个完全相同的大小;)
ProfHase85

5

另一个解决方案:

import sh
sh.rm(sh.glob('/path/to/folder/*'))

1
请注意,sh它不是标准库的一部分,需要使用PyPI进行安装才能使用。另外,由于这实际上是rm在子进程中调用的,因此在rm不存在的Windows上将无法使用。如果文件夹包含任何子目录,也会引发异常。
Mark Amery

5

我知道这是一个旧线程,但是我从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))

4

要删除目录及其子目录中的所有文件而不删除文件夹本身,只需执行以下操作:

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

3

如果使用的是* nix系统,为什么不利用system命令?

import os
path = 'folder/to/clean'
os.system('rm -rf %s/*' % path)

3
因为,正如问题中所述,“当前项目适用于Windows”
与莫妮卡

3

相当直观的方式:

import shutil, os


def remove_folder_contents(path):
    shutil.rmtree(path)
    os.makedirs(path)


remove_folder_contents('/path/to/folder')

3

好吧,我认为这段代码可以正常工作。它不会删除该文件夹,您可以使用此代码删除具有特定扩展名的文件。

import os
import glob

files = glob.glob(r'path/*')
for items in files:
    os.remove(items)

3

我必须从单个父目录中的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)

希望这可以帮助。


1

rmtree makedirs通过添加以下内容解决了该问题time.sleep()

if os.path.isdir(folder_location):
    shutil.rmtree(folder_location)

time.sleep(.5)

os.makedirs(folder_location, 0o777)

0

回答有限的特定情况:假设您要在维护子文件夹树时删除文件,则可以使用递归算法:

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)

也许有点题外话,但我认为许多人会觉得有用


os.walkstackoverflow.com/a/54889532/1709587所示的方式使用,可能是删除所有文件的完整方法,同时保持目录结构完整。
Mark Amery

-1

假设temp_dir要删除,使用的单行命令os将是:

_ = [os.remove(os.path.join(save_dir,i)) for i in os.listdir(temp_dir)]

注意:这只是删除文件的1线。

希望这可以帮助。谢谢。


-1

使用下面的方法删除目录的内容,而不是目录本身:

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 Negative
Amir Rezazadeh

谢谢阿米尔,我正在寻找一种解决方案,该解决方案可在根目录的所有子目录中找到某个文件夹并删除该文件夹的内容
FabioSpaghetti

在您发布此内容之前,这不会添加在接受的答案年份中尚未显示的新内容。
Mark Amery

-1

删除文件夹中的所有文件/删除所有文件的最简单方法

import os
files = os.listdir(yourFilePath)
for f in files:
    os.remove(yourFilePath + f)

如果有子目录,则失败。
Mark Amery

-3

仅使用OS模块列出然后删除,就可以达到目的。

import os
DIR = os.list('Folder')
for i in range(len(DIR)):
    os.remove('Folder'+chr(92)+i)

为我工作,任何问题都让我知道!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.