2015-02-09 20 views
7

Tüm boş dizinleri yinelemeli olarak silen bir Python işlevi yazmaya çalışıyorum. Bu, "a" dizini sadece "b" içeriyorsa, "b" 'nin silinmesi gerektiği anlamına gelir, sonra "a" silinmelidir (artık hiçbir şey içermediğinden). Bir dizin bir şey içeriyorsa, atlanır. Resimli:Neden python'un os.walk() dizini silinmesini yansıtmıyor?

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

bu göz önüne alındığında, üç dizinleri "b", "a" ve "foo" silinmesi gerektiğini, "foo" ve "b" olarak "bir" boş olacak şimdi boş olan ve "b" nin silinmesinden sonra.

Bunu, os.walk ve shutil.rmtree aracılığıyla yapmaya çalışıyorum. Maalesef, kodum yalnızca ilk dizin seviyesini siliyor, ancak süreçte yeni boşaltılanları değil.

os.walk'un topdown=false parametresini kullanıyorum. os.walk için documentation, "Topdown False ise, bir dizinin üçlüsü tüm alt dizinleri için üçlüden sonra oluşturulur (dizinler aşağıdan oluşturulur)." Gördüğüm şey bu değil. İşte

benim kod:

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 

Ben dizin yapısı yukarıda açıklanan varsa, burada ne olsun: Ben "b" kaldırmış halde

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

Not, yani " Bir "kaldırılmıyor, hala" b "içerdiğini düşünerek. Kafam karıştıran şey, os.walk belgelerinin, "b" için üçlüyü oluşturan'un ardından "./a" için üçlü oluşturduğunu söylemektir. Çıktım aksini gösteriyor. "./c" için benzer bir hikaye. Kapıdan çıkarmış olsam bile, hala "foo" olduğunu gösteriyor.

Neyi yanlış yapıyorum? (Python 2.6.6 kullanıyorum.)

+0

Beklemezdim.'for' döngüsü – jcfollower

+0

her yinelemede güncellenmesi için yürümek anahtar sanırım. Dokümantasyondaki "önce" ve "sonra", "for" döngüsü boyunca ardışık yinelemelerin zamansal bir sıralaması değil, os.walk() 'ile sonuçlanan dizi çıktısındaki sıraya atıfta bulunur. 'Topdown = True' modunda arayanın 'dirnames' argümanını değiştirebilmesi, yinelemenin etkilenebileceğini düşünmeme yol açtı. – seanahern

cevap

2

jcfollower cevabı karşılaştığınız sorunu nedeni hakkında kesinlikle doğrudur. Bu, gerçekleştirdiğiniz dosya sistemi değişikliklerinin daha sonraki sonuçlarda yansıtılmayacağı anlamına gelir. üç yeni satır vardır

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 

:

bu sorununa çözüm bulunması Eğer alt dizin ebeveynlerinin listesinin olarak filtreler, böylece silinmiş dizinleri bir dizi sağlamaktır. İlk, üstte, kaldırılan dizinleri içerecek şekilde boş bir removed oluşturur. İkincisi dirs listesinin yerini, önceki bir adımda silindikleri için çıkarılmış kümedeki alt dizinleri içermeyen yeni bir listeyle değiştirir. Son yeni satır, mevcut dizini kaldırıldığında kümeye ekler.

+0

Bu düzgün bir numara! Çok zeki. 'Os.walk()' ın, silme işlemleriyle muhtemelen geçersiz kılınan bilgileri vereceğini ve bunun ne getirdiğini açıkça değiştirdiğini kabul eder. – seanahern

9

documentation bu var ...

olursa olsun tepeden-aşağı değeri, alt dizinleri listesi dizin ve onun için küpe önce alınır altdizinler üretilmektedir. Sonuçlar tabandan tavana şekilde os.walk den vermiştir bile, dosya sistemi her zaman yukarıdan aşağı okunur:

+0

Bu, şu ana kadar en iyi cevaptır. 'Topdown = False' temelde dosya sistemi araştırmasının zamansal sıralamasını değil, os.walk() 'ın çıkışında bir veri siparişi sorunu olduğunu söylüyor. – seanahern

İlgili konular