2014-02-24 191 views
6

刪除空目錄,我有以下結構:掃描文件遞歸和蟒蛇

Dir 1 
|___Dir 2 
    |___file 1 
    |___file 2... 
Dir 3 
|___Dir 4 
    |___file 3... 

我希望能夠找到每個文件遞歸過程中我自己的方式文件,一旦完成,刪除文件,移到下一個。然後,如果該目錄是空的,請刪除該目錄,繼續工作,直到沒有任何內容。

只是沒有確定如何進行。

這是我有:

for root, dirs, files in os.walk(dir): 
    path = root.split('/') 
    for file in files: 
     file = os.path.join(root, file) 
     process_file(file) 
     os.remove(file) 

這很好,但我想,然後刪除子目錄,如果只有他們是空的。

+0

你嘗試過什麼?您使用什麼軟件包來瀏覽/瀏覽文件樹? – JonathanV

+0

嗨。你看起來很新。如果您希望人們幫助您,我鼓勵您知道向我們展示您迄今爲止編寫的代碼,我們會盡力從此基礎爲您提供幫助。 – Ketouem

+0

執行'os.walk'來獲取所有文件,執行'os.path.join'獲取完整的文件路徑進行處理。最終刪除根目錄(這將刪除它下面的所有內容) – inspectorG4dget

回答

5

唉,我想這會做,必須運行雖然... os.walk

def get_files(src_dir): 
# traverse root directory, and list directories as dirs and files as files 
    for root, dirs, files in os.walk(src_dir): 
     path = root.split('/') 
     for file in files: 
      process(os.path.join(root, file)) 
        os.remove(os.path.join(root, file)) 

def del_dirs(src_dir): 
    for dirpath, _, _ in os.walk(src_dir, topdown=False): # Listing the files 
     if dirpath == src_dir: 
      break 
     try: 
      os.rmdir(dirpath) 
     except OSError as ex: 
      print(ex) 


def main(): 
    get_files(src_dir) 
    del_dirs(src_dir) 


if __name__ == "__main__": 
    main() 
0

這只是刪除空目錄,並拉出目錄的單個文件。它似乎只回答問題的一部分,抱歉。

我在結尾加上一個循環來不斷嘗試,直到它再也找不到。我讓這個函數返回一個被刪除的目錄。

我拒絕訪問錯誤被固定的:shutil.rmtree fails on Windows with 'Access is denied'

import os 
import shutil 


def onerror(func, path, exc_info): 
    """ 
    Error handler for ``shutil.rmtree``. 

    If the error is due to an access error (read only file) 
    it attempts to add write permission and then retries. 

    If the error is for another reason it re-raises the error. 

    Usage : ``shutil.rmtree(path, ignore_errors=False, onerror=onerror)`` 
    """ 
    import stat 

    if not os.access(path, os.W_OK): 
     # Is the error an access error ? 
     os.chmod(path, stat.S_IWUSR) 
     func(path) 
    else: 
     raise 


def get_empty_dirs(path): 
    # count of removed directories 
    count = 0 
    # traverse root directory, and list directories as dirs and files as files 
    for root, dirs, files in os.walk(path): 
     try: 
      # if a directory is empty there will be no sub-directories or files 
      if len(dirs) is 0 and len(files) is 0: 
       print u"deleting " + root 
       # os.rmdir(root) 
       shutil.rmtree(root, ignore_errors=False, onerror=onerror) 
       count += 1 
      # if a directory has one file lets pull it out. 
      elif len(dirs) is 0 and len(files) is 1: 
       print u"moving " + os.path.join(root, files[0]) + u" to " + os.path.dirname(root) 
       shutil.move(os.path.join(root, files[0]), os.path.dirname(root)) 
       print u"deleting " + root 
       # os.rmdir(root) 
       shutil.rmtree(root, ignore_errors=False, onerror=onerror) 
       count += 1 
     except WindowsError, e: 
      # I'm getting access denied errors when removing directory. 
      print e 
     except shutil.Error, e: 
      # Path your moving to already exists 
      print e 
    return count 


def get_all_empty_dirs(path): 
    # loop till break 
    total_count = 0 
    while True: 
     # count of removed directories 
     count = get_empty_dirs(path) 
     total_count += count 
     # if no removed directories you are done. 
     if count >= 1: 
      print u"retrying till count is 0, currently count is: %d" % count 
     else: 
      break 

    print u"Total directories removed: %d" % total_count 
    return total_count 


count = get_all_empty_dirs(os.getcwdu()) # current directory 
count += get_all_empty_dirs(u"o:\\downloads\\") # other directory 
print u"Total of all directories removed: %d" % count 
3

我知道這個帖子是老年人和有可能在加入另外的例子是沒有意義的,而且一目瞭然我認爲這將是一個更容易初學者比其他人更容易掌握,因爲沒有加入,它只導入一個模塊,並且它提供了很好的例子,說明如何使用一些內置函數[open()& len()]和帶有str的新Python3字符串格式。格式。它還顯示瞭如何使用file = filename在print()函數中將簡單的內容填充到文件中。

該腳本將掃描具有os.walk()根目錄,檢查目錄和文件的長度,並基於其發現的情況。它還會增加一個計數器,以確定使用的目錄數量爲&,並將其輸出到文件中。我在Python 3.4中編寫了這個例子,它適用於我的目的。如果有人有改進邏輯的想法,請在評論中張貼,這樣我們都可以學習解決問題的新視角。

import os 
#declare the root directory 
root_dir = 'C:\\tempdir\\directory\\directory\\' 
#initialize the counters 
empty_count = 0 
used_count = 0 
#Set the file to write to. 'x' will indicate to create a new file and open it for writing 
outfile = open('C:\\tempdir\\directories.txt', 'x') 
for curdir, subdirs, files in os.walk(root_dir): 
    if len(subdirs) == 0 and len(files) == 0: #check for empty directories. len(files) == 0 may be overkill 
     empty_count += 1 #increment empty_count 
     print('Empty directory: {}'.format(curdir), file = outfile) #add empty results to file 
     os.rmdir(curdir) #delete the directory 
    elif len(subdirs) > 0 and len(files) > 0: #check for used directories 
     used_count += 1 #increment used_count 
     print('Used directory: {}'.format(curdir), file = outfile) #add used results to file 

#add the counters to the file 
print('empty_count: {}\nused_count: {}'.format(empty_count, used_count), file = outfile) 
outfile.close() #close the file 
0
import os 

#Top level of tree you wish to delete empty directories from. 
currentDir = r'K:\AutoCAD Drafting Projects\USA\TX\Image Archive' 

index = 0 

for root, dirs, files in os.walk(currentDir): 
    for dir in dirs: 
     newDir = os.path.join(root, dir) 
     index += 1 
     print str(index) + " ---> " + newDir 

     try: 
      os.removedirs(newDir) 
      print "Directory empty! Deleting..." 
      print " " 
     except: 
      print "Directory not empty and will not be removed" 
      print " " 

尼斯和簡單。關鍵是在try語句下使用os.removedirs。它已經遞歸。

0

這裏是另一種解決辦法,我認爲是有效的。當然,使用os.scandir可以提高效率。

首先,我定義了一個通用rec_rmdir功能(reccursive命令rmdir)的瀏覽目錄樹遞歸。

  • 該函數首先處理每個文件和每個子目錄。
  • 然後它會嘗試刪除當前目錄。
  • 保留標誌用於保留根目錄。

該算法是一個典型的Depth-first search

import os 
import stat 


def rec_rmdir(root, callback, preserve=True): 
    for path in (os.path.join(root, p) for p in os.listdir(root)): 
     st = os.stat(path) 
     if stat.S_ISREG(st.st_mode): 
      callback(path) 
     elif stat.S_ISDIR(st.st_mode): 
      rec_rmdir(path, callback, preserve=False) 
    if not preserve: 
     try: 
      os.rmdir(root) 
     except IOError: 
      pass 

然後,很容易定義一個處理文件並將其刪除的函數。

def process_file_and_remove(path): 
    # process the file 
    # ... 
    os.remove(path) 

的經典用法:

rec_rmdir("/path/to/root", process_file_and_remove)