【问题标题】:PathLib recursively remove directory?PathLib递归删除目录?
【发布时间】:2018-10-15 15:33:38
【问题描述】:

有什么方法可以删除 PathLib 模块中的目录及其内容? path.unlink() 只删除一个文件,path.rmdir() 目录必须为空。有没有办法在一个函数调用中做到这一点?

【问题讨论】:

    标签: python directory pathlib


    【解决方案1】:

    如您所知,用于删除文件/目录的仅有两种 Path 方法是 .unlink().rmdir(),这两种方法都不是您想要的。

    Pathlib 是一个提供跨不同操作系统的面向对象路径的模块,它并不意味着有很多不同的方法。

    这个库的目的是提供一个简单的类层次结构 处理文件系统路径和用户对其进行的常见操作。

    “不常见”的文件系统更改(例如递归删除目录)存储在不同的模块中。如果你想递归删除一个目录,你应该使用shutil 模块。 (它也适用于 Path 实例!)

    import shutil
    import pathlib
    import os  # for checking results
    
    print(os.listdir())
    # ["a_directory", "foo.py", ...]
    
    path = pathlib.Path("a_directory")
    
    shutil.rmtree(path)
    print(os.listdir())
    # ["foo.py", ...]
    

    【讨论】:

    • 只是提一下,可以这样-stackoverflow.com/a/49782093/4249707
    • 我还是不明白,为什么递归版本不是 pathlib.Path 的一部分,当一切都已经存在时,需要的东西已经存在。我真的希望,os.path、os.mkdir、shutil 等的这种令人困惑的用法会以 pathlib 结尾。
    • @SebastianWerk 公关!公关!公关! -- 虽然在标准库中,但遗憾的是它暂时不会出局,并且需要付出很多努力才能进入。我同意你的观点
    【解决方案2】:

    这是一个纯路径库实现:

    from pathlib import Path
    
    
    def rm_tree(pth):
        pth = Path(pth)
        for child in pth.glob('*'):
            if child.is_file():
                child.unlink()
            else:
                rm_tree(child)
        pth.rmdir()
    

    【讨论】:

    • 我想这会删除符号链接目录的内容吗?
    【解决方案3】:

    否则,如果你只想要pathlib,你可以试试这个:

    from pathlib import Path
    
    
    def rm_tree(pth: Path):
        for child in pth.iterdir():
            if child.is_file():
                child.unlink()
            else:
                rm_tree(child)
        pth.rmdir()
    
    rm_tree(your_path)
    

    【讨论】:

    • os 在 Anton 的建议下不再使用。
    • 对正在迭代的目录进行变异是否安全?在开始迭代之前,可能必须将iterdir() 的完整结果提取到一个列表中。
    • 递归函数将继续删除文件(child.unlink()),直到目录为空。一旦为空,目录将被删除 (pth.rmdir())。
    【解决方案4】:

    如果您不介意使用第三方库,请尝试path。 它的 API 类似于 pathlib.Path,但提供了一些额外的方法,包括 Path.rmtree() 递归删除目录树。

    【讨论】:

      【解决方案5】:
      def rm_rf(basedir):
          if isinstance(basedir,str): basedir = pathlib.Path(basedir)
          if not basedir.is_dir(): return
          for p in reversed(list(basedir.rglob("*"))):
              if p.is_file(): p.unlink()
              elif p.is_dir(): p.rmdir()
          basedir.rmdir()
      

      【讨论】:

        【解决方案6】:

        您可以使用 pathlib3x - 它提供了最新的(在撰写此答案 Python 3.10.a0 之日)Python 3.6 或更高版本的 Python pathlib 的反向移植,以及一些额外的功能,如 rmtree

        >>> python -m pip install pathlib3x
        
        >>> import pathlib3x as pathlib
        
        >>> my_path = pathlib.Path('c:/tmp/some_directory')
        >>> my_path.rmtree(ignore_errors=True)
        
        
        

        您可以在githubPyPi 上找到它


        免责声明:我是 pathlib3x 库的作者。

        【讨论】:

          【解决方案7】:

          简单有效:

          def rmtree(f: Path):
              if f.is_file():
                  f.unlink()
              else:
                  for child in f.iterdir():
                      rmtree(child)
                  f.rmdir()
          

          【讨论】:

            猜你喜欢
            • 2014-05-12
            • 2018-11-15
            • 1970-01-01
            • 2010-10-21
            • 2016-04-18
            • 1970-01-01
            相关资源
            最近更新 更多