【问题标题】:Deleting folders in python recursively递归删除python中的文件夹
【发布时间】:2012-10-18 13:19:16
【问题描述】:

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

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/...

请注意,以上所有文件夹都是空的。当我运行这个脚本时,文件夹20,25 被单独删除!但是文件夹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 正在删除整个目录。这意味着该目录是一个空目录!

标签: python directory


【解决方案1】:

试试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))
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

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

    命令(由 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 *
    【解决方案5】:

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

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

    【讨论】:

      【解决方案6】:

      这是我的纯 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 是异步的
      【解决方案7】:

      对于下一个寻找 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)
      

      【讨论】:

        【解决方案8】:

        这是一个递归解决方案:

        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)
        

        【讨论】:

          【解决方案9】:

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

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

          【讨论】:

            【解决方案10】:

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

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

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

            其中rm 代表删除-r 代表递归-rf 代表递归+强制

            注意:无论目录是否为空,它们都会被删除。

            【讨论】:

            • 当你使用python但是代码依赖于系统时,它不再是pythonic。
            • @LukAron 我说过,“Python 方式的 shell 命令”不仅仅是“python 方式”
            【解决方案11】:

            命令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.
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-03-29
              • 2014-06-21
              • 2012-11-19
              • 2015-08-02
              • 2016-06-09
              • 2015-01-18
              相关资源
              最近更新 更多