为什么python的os.walk()不反映目录删除?

时间:2015-02-09 20:25:22

标签: python os.walk

我试图编写一个递归删除所有空目录的Python函数。这意味着如果目录" a"仅包含" b"," b"应删除,然后" a"应删除(因为它现在不包含任何内容)。如果目录包含任何内容,则会跳过该目录。所示:

top/a/b/
top/c/d.txt
top/c/foo/

鉴于此,三个目录" b"," a"和" foo"应删除,因为" foo"和" b"现在是空的," a"删除" b"。

后将变为空

我尝试通过os.walkshutil.rmtree执行此操作。不幸的是,我的代码只删除了第一级目录,但没有删除过程中新清空的目录。

我正在使用topdown=false的{​​{1}}参数。 os.walk os.walk表示"如果topdown为False,则在所有子目录的三元组(目录是自下而上生成)之后生成目录的三元组。&#34 ;那不是我所看到的。

这是我的代码:

for root, dirs, files in os.walk(".", topdown=False):
  contents = dirs+files
  print root,"contains:",contents
  if len(contents) == 0:
    print 'Removing "%s"'%root
    shutil.rmtree(root)
  else:
    print 'Not removing "%s". It has:'%root,contents

如果我有上述目录结构,请参阅以下内容:

./c/foo contains: []
Removing "./c/foo"
./c contains: ['foo', 'd.txt']
Not removing "./c". It has: ['foo', 'd.txt']
./a/b contains: []
Removing "./a/b"
./a contains: ['b']
Not removing "./a". It has: ['b']
. contains: ['c', 'a']
Not removing ".". It has: ['c', 'a']

请注意,即使我已删除" b"," a"没有删除,认为它仍然包含" b"。我感到困惑的是,os.walk的文档说它会为" ./ a"生成三元组。 生成" b"的三元组后。我的输出表明不然。类似的故事为" ./ c"。它表明它仍然有" foo",即使我已经将它从门外删除了。

我做错了什么? (我使用的是Python 2.6.6。)

2 个答案:

答案 0 :(得分:9)

documentation有这个......

  

无论topdown的值如何,子目录列表都是   在目录及其子目录的元组之前检索   生成。

答案 1 :(得分:2)

jcfollower的答案对于您遇到的问题的原因绝对正确:文件系统始终自上而下读取,即使结果是从底部的os.walk得出的的方式。这意味着您执行的文件系统修改不会反映在后面的结果中。

此问题的解决方案是维护一组已删除的目录,以便您可以从父目录的子目录列表中过滤它们:

removed = set()                                               # first new line
for root, dirs, files in os.walk(".", topdown=False):
      dirs = [dir for dir in dirs if os.path.join(root, dir) not in removed] # second
      contents = dirs+files
      print root,"contains:",contents
      if len(contents) == 0:
          print 'Removing "%s"'%root
          shutil.rmtree(root)
          removed.add(root)                                   # third new line
      else:
          print 'Not removing "%s". It has:'%root,contents

有三条新线。第一个,在顶部,创建一个空removed集以包含已删除的目录。第二个替换dirs列表的新列表不包含已删除集中的任何子目录,因为它们在上一步中被删除。最后一个新行将当前目录添加到已删除的集合中。