2014-11-06 3 views
4

Аналогично GNU findfind . -type d -empty -delete Я бы хотел найти пустые каталоги, в том числе с пустыми подкаталогами (и подкаталогами, содержащими подтипы emtpy и т. Д.), Но без их удаления. Есть ли существующее решение или мне нужно вручную использовать os.walk (возможно, с topdown=False и отслеживать пустые подкаталоги, найденные до сих пор)?Как найти рекурсивно пустые каталоги в Python?

+0

Я попытался бы использовать 'os.walk', или' 'Popen' + find', если я был уверен, что работать на Unix/Linux –

+0

@SergeBallesta Первое мое предположение до сих пор тоже. Мне было интересно, есть ли для него библиотечная функция, хотя ... Или, может быть, модуль 'find'. Это может упростить многие вещи. –

+0

@SergeBallesta I [реализовано с помощью 'os.walk'] (http://stackoverflow.com/a/26775425/321973), надеюсь, что это достаточно Pythonic ... –

ответ

2

Хорошо, вот мое руководство с использованием os.walk. Функцию is_empty можно, конечно, модифицировать, например. чтобы исключить скрытые файлы, или в моем примере desktop.ini:

import os 


def empty_dirs(root_dir='.', recursive=True): 
    empty_dirs = [] 
    for root, dirs, files in os.walk(root_dir, topdown=False): 
     #print root, dirs, files 
     if recursive: 
      all_subs_empty = True # until proven otherwise 
      for sub in dirs: 
       full_sub = os.path.join(root, sub) 
       if full_sub not in empty_dirs: 
        #print full_sub, "not empty" 
        all_subs_empty = False 
        break 
     else: 
      all_subs_empty = (len(dirs) == 0) 
     if all_subs_empty and is_empty(files): 
      empty_dirs.append(root) 
      yield root 


def is_empty(files): 
    return (len(files) == 0 or files == ['desktop.ini']) 


def find_empty_dirs(root_dir='.', recursive=True): 
    return list(empty_dirs(root_dir, recursive)) 


print find_empty_dirs(recursive=False) 
6

Вот простое решение с помощью генератора и os.walk:

import os 

def find_empty_dirs(root_dir='.'): 
    for dirpath, dirs, files in os.walk(root_dir): 
     if not dirs and not files: 
      yield dirpath 

print list(find_empty_dirs()) 

Я не вижу, почему topdown=False надо, я не думаю, что это что-то меняет.

Это относится к каталогам, которые содержат только пустые каталоги, которые сами не являются пустыми, но тогда find . -type d -empty.

Хотя, с некоторыми более тестирования, я вижу find . -type d -empty -deleteли удалить пустые подкаталоги, а затем каталоги более, если это сделало их пустыми. Но использование os.walk для этого не будет работать, поскольку оно считывает список подкаталогов до спуска, даже с topdown=False.

Рекурсивный решение, которое удаляет пустые подкатлоге деревья могут быть:

import os 

def recursive_delete_if_empty(path): 
    """Recursively delete empty directories; return True 
    if everything was deleted.""" 

    if not os.path.isdir(path): 
     # If you also want to delete some files like desktop.ini, check 
     # for that here, and return True if you delete them. 
     return False 

    # Note that the list comprehension here is necessary, a 
    # generator expression would shortcut and we don't want that! 
    if all([recursive_delete_if_empty(os.path.join(path, filename)) 
      for filename in os.listdir(path)]): 
     # Either there was nothing here or it was all deleted 
     os.rmdir(path) 
     return True 
    else: 
     return False 
+0

Любопытный - ах, я вижу свою ошибку в вопросе 'find. -type d -empty' работает рекурсивно, как я имел в виду при использовании '-delete'. Я боюсь, что мне нужно исправить свой вопрос, хотя ваш вклад приветствуется, генератор лучше звучит в любом случае –

+0

Я изменил [свой собственный ответ] (http://stackoverflow.com/a/26775425/321973), чтобы включить генератор, но до сих пор я должен хранить все пустые поддиры, найденные до сих пор, поэтому я требую 'topdown = False'. Но, может быть, это проще? –

Смежные вопросы