I'm attempting to write a Python function that will recursively delete all empty directories. This means that if directory "a" contains only "b", "b" should be deleted, then "a" should be deleted (since it now contains nothing). If a directory contains anything, it is skipped. Illustrated:
top/a/b/
top/c/d.txt
top/c/foo/
Given this, the three directories "b", "a", and "foo" should be deleted, as "foo" and "b" are empty now, and "a" will become empty after the deletion of "b".
I'm attempting to do this via os.walk
and shutil.rmtree
. Unfortunately, my code is only deleting the first level of directories, but not ones newly emptied in the process.
I'm using the topdown=false
parameter of os.walk
. The documentation for os.walk
says that "If topdown is False, the triple for a directory is generated after the triples for all of its subdirectories (directories are generated bottom-up)." That's not what I'm seeing.
Here's my code:
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
If I have the directory structure described above, here's what I get:
./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']
Note that, even though I've removed "b", "a" is not removed, thinking that it still contains "b". What I'm confused about is that the documentation for os.walk
says that it generates the triple for "./a" after generating the triple for "b". My output suggests otherwise. Similar story for "./c". It shows that it still has "foo", even though I had deleted it right out of the gate.
What am I doing wrong? (I'm using Python 2.6.6.)
for
loop – Chemoprophylaxisos.walk()
, not a temporal ordering of successive iterations through thefor
loop. The fact that the caller, intopdown=True
mode, can modify thedirnames
argument led me to think that iteration can be affected. – Mesquite