ChatGPT解决这个技术问题 Extra ChatGPT

递归删除python中的文件夹

我在删除空目录时遇到问题。这是我的代码:

for dirpath, dirnames, filenames in os.walk(dir_to_search):
    //other codes

    try:
        os.rmdir(dirpath)
    except OSError as ex:
        print(ex)

参数 dir_to_search 是我传递需要完成工作的目录的位置。该目录如下所示:

test/20/...
test/22/...
test/25/...
test/26/...

请注意,以上所有文件夹都是空的。当我运行此脚本时,仅文件夹 2025 就会被删除!但是文件夹 2526 不会被删除,即使它们是空文件夹。

编辑:

我得到的例外是:

[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/29'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/29/tmp'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/28'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/28/tmp'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/26'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/25'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/27'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/27/tmp'

我在哪里犯错?

你确定他们没有隐藏文件吗?
是否打印了异常或回溯?如果是这样-如果您将其添加到问题中会有所帮助
@Jeff:是的,我确定。事实上,在我的 ubuntu 机器上,我尝试 rmdir /path/to/25th/folder 正在删除整个目录。这意味着该目录是一个空目录!

B
Boris Verkhovskiy

试试 shutil.rmtree

import shutil
shutil.rmtree('/path/to/your/dir/')

rmtree 是否删除了整个目录?我猜它类似于rm -Rf $DIR
请小心,因为 rmtree 也会删除文件。如所问,问题是如何删除 EMPTY 目录。 os.walk 的文档给出了一个几乎完全匹配这个问题的例子:import os for root, dirs, files in os.walk(top, topdown=False): for name in dirs: os.rmdir(os.path.join(root, name))
B
Boris Verkhovskiy

这是我的纯 pathlib 递归目录取消链接器:

from pathlib import Path

def rmdir(directory):
    directory = Path(directory)
    for item in directory.iterdir():
        if item.is_dir():
            rmdir(item)
        else:
            item.unlink()
    directory.rmdir()

rmdir(Path("dir/"))

假设shutil更好,因此shutil是异步的
非常好,并且是递归作为奖励的具体示例。
L
Leland Hepworth

os.walk() 的默认行为是从根走到叶。在 os.walk() 中设置 topdown=False 以从叶子走到根。


B
Boris Verkhovskiy

在 Python 标准库的 shutil 中尝试 rmtree()


rmtree 是否删除了整个目录?我猜它类似于rm -Rf $DIR
来自文档:“删除整个目录树;路径必须指向一个目录(但不是指向目录的符号链接)。如果 ignore_errors 为真,则由于删除失败而导致的错误将被忽略;如果为假或省略,则处理此类错误通过调用由 onerror 指定的处理程序,或者,如果省略,它们会引发异常。”
G
Gajender

最好使用绝对路径并仅导入 rmtree 函数 from shutil import rmtree,因为这是一个大包,上面的行只会导入所需的函数。

from shutil import rmtree
rmtree('directory-absolute-path')

J
Justus Wingert

只是对于下一个搜索 micropython 解决方案的人来说,这完全基于 os (listdir, remove, rmdir)。它既不完整(尤其是在错误处理中)也不花哨,但它在大多数情况下都可以工作。

def deltree(target):
    print("deltree", target)
    for d in os.listdir(target):
        try:
            deltree(target + '/' + d)
        except OSError:
            os.remove(target + '/' + d)

    os.rmdir(target)

A
Azat Ibrakov

如果文件是只读的,该命令(由 Tomek 给出)不能删除文件。因此,可以使用 -

import os, sys
import stat

def del_evenReadonly(action, name, exc):
    os.chmod(name, stat.S_IWRITE)
    os.remove(name)

if  os.path.exists("test/qt_env"):
    shutil.rmtree('test/qt_env',onerror=del_evenReadonly)

在尝试使用我自己的要删除的文件夹的代码时,我收到一条错误消息:NameError: name 'stat' is not defined。它是如何定义的?
stat 模块定义了用于解释 os.stat()、os.fstat() 和 os.lstat() 结果的常量和函数。你可以尝试什么:import os, sys from stat import *
T
Tobias Ernst

这是一个递归解决方案:

def clear_folder(dir):
    if os.path.exists(dir):
        for the_file in os.listdir(dir):
            file_path = os.path.join(dir, the_file)
            try:
                if os.path.isfile(file_path):
                    os.unlink(file_path)
                else:
                    clear_folder(file_path)
                    os.rmdir(file_path)
            except Exception as e:
                print(e)

C
Cireo

如果您只是在寻找要删除的单个路径,则命令 os.removedirs 是该作业的工具,例如:

os.removedirs("a/b/c/empty1/empty2/empty3")

将删除 empty1/empty2/empty3,但保留 a/b/c(假设 c 有一些其他内容)。

    removedirs(name)
        removedirs(name)
        
        Super-rmdir; remove a leaf directory and all empty intermediate
        ones.  Works like rmdir except that, if the leaf directory is
        successfully removed, directories corresponding to rightmost path
        segments will be pruned away until either the whole path is
        consumed or an error occurs.  Errors during this latter phase are
        ignored -- they generally mean that a directory was not empty.

p
pepoluan

这是另一个纯路径库解决方案,但没有递归:

from pathlib import Path
from typing import Union

def del_empty_dirs(base: Union[Path, str]):
    base = Path(base)
    for p in sorted(base.glob('**/*'), reverse=True):
        if p.is_dir():
            p.chmod(0o666)
            p.rmdir()
        else:
            raise RuntimeError(f'{p.parent} is not empty!')
    base.rmdir()

b
buhtz

这是一个pythonic和无递归的解决方案

>>> for e in sorted(p.rglob('**/*'), key=lambda v: v.is_dir()):
...     try:
...         e.unlink()
...     except IsADirectoryError:
...         e.rmdir()

rglob() 以递归方式为您提供路径 p 中的所有文件和目录。 sorted() 及其 key 参数负责将结果按文件排序,然后按目录排序。这使得可以通过首先删除它们的文件来使所有目录为空。

try...except... 部分阻止您使用廉价的 if 语句。


G
Garvit

对于Linux用户,您可以简单地以pythonic方式运行shell命令

import os
os.system("rm -r /home/user/folder1  /home/user/folder2  ...")

如果遇到任何问题,请使用 rm -rf 而不是 rm -r,但请记住 f 将强制删除目录。

其中 rm 代表 remove-r 代表 recursively,而 -rf 代表 recursively + forcefully

注意:目录是否为空都没有关系,它们将被删除。


但是,当您使用 python 时,代码是依赖于系统的,它不再是 pythonic。
@LukAron我说过,“以pythonic方式执行shell命令”不仅仅是“pythonic方式”