python移除/刪除非空資料夾/目錄的最有效方法是什麼?

小小程序员ol發表於2024-02-28

1.標準庫參考:shutil.rmtree。

根據設計,rmtree在包含只讀檔案的資料夾樹上失敗。如果要刪除資料夾,不管它是否包含只讀檔案,請使用

import shutil
shutil.rmtree('/folder_name', ignore_errors=True)

2.從os.walk()上的python文件中:

# Delete everything reachable from the directory named in 'top',
# assuming there are no symbolic links.
# CAUTION:  This is dangerous!  For example, if top == '/', it
# could delete all your disk files.
import os
for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        os.remove(os.path.join(root, name))
    for name in dirs:
        os.rmdir(os.path.join(root, name))

3.從python 3.4可以使用:

import pathlib
 
def delete_folder(pth) :
    for sub in pth.iterdir() :
        if sub.is_dir() :
            delete_folder(sub)
        else :
            sub.unlink()
    pth.rmdir() # if you just want to delete dir content, remove this line 

其中pth是pathlib.Path例項。很好,但可能不是最快的。

import os
import stat
import shutil
 
def errorRemoveReadonly(func, path, exc):
    excvalue = exc[1]
    if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
        # change the file to be readable,writable,executable: 0777
        os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)  
        # retry
        func(path)
    else:
        # raiseenter code here
 
shutil.rmtree(path, ignore_errors=False, onerror=errorRemoveReadonly)

如果設定了ignore_errors,則忽略錯誤;否則,如果設定了onerror,則呼叫它以使用引數(func、path、exc_info)處理錯誤,其中func是os.listdir、os.remove或os.rmdir;path是導致函式失敗的函式的引數;exc_infosys.exc_info()返回的元組。如果"忽略錯誤"為"假",而"OnError"為"無",則會引發異常。請在此處輸入程式碼。

只需一些python3.5選項就可以完成上面的答案

刪除空資料夾

import os
import shutil
from send2trash import send2trash # (shutil delete permanently)
 
root = r"C:\Users\Me\Desktop\test"  
for dir, subdirs, files in os.walk(root):  
    if subdirs == [] and files == []:
           send2trash(dir)
           print(dir,": folder removed")
   # 如果資料夾包含此檔案,請同時刪除它
   elif subdirs == [] and len(files) == 1: # if contains no sub folder and only 1 file
        if files[0]=="desktop.ini" or:  
            send2trash(dir)
            print(dir,": folder removed")
        else:
            print(dir)
 
    #刪除僅包含.srt或.txt檔案的資料夾
    elif subdirs == []: #if dir doesn’t contains subdirectory
        ext = (".srt",".txt")
        contains_other_ext=0
        for file in files:
            if not file.endswith(ext):  
                contains_other_ext=True
        if contains_other_ext== 0:
                send2trash(dir)
                print(dir,": dir deleted")    

如果資料夾大小小於400KB,則刪除該資料夾:

def get_tree_size(path):
   """Return total size of files in given path and subdirs."""
    total = 0
    for entry in os.scandir(path):
        if entry.is_dir(follow_symlinks=False):
            total += get_tree_size(entry.path)
        else:
            total += entry.stat(follow_symlinks=False).st_size
    return total
 
 
for dir, subdirs, files in os.walk(root):  
    If get_tree_size(dir) < 400000:  # ≈ 400kb
        send2trash(dir)
    print(dir,"dir deleted") 

如果您確定要刪除整個目錄樹,並且對目錄的內容不再感興趣,那麼對整個目錄樹進行爬行是愚蠢的…只需從python呼叫本機作業系統命令即可。它將更快、更高效,而且記憶體消耗更少。

RMDIR c:\blah /s /q

或* nix

rm -rf /home/whatever

在Python中,程式碼看起來像..

import sys
import os
 
mswindows = (sys.platform =="win32")
 
def getstatusoutput(cmd):
   """Return (status, output) of executing cmd in a shell."""
    if not mswindows:
        return commands.getstatusoutput(cmd)
    pipe = os.popen(cmd + ' 2>&1', 'r')
    text = pipe.read()
    sts = pipe.close()
    if sts is None: sts = 0
    if text[-1:] == '
': text = text[:-1]
    return sts, text
 
 
def deleteDir(path):
   """deletes the path entirely"""
    if mswindows:
        cmd ="RMDIR"+ path +" /s /q"
    else:
        cmd ="rm -rf"+path
    result = getstatusoutput(cmd)
    if(result[0]!=0):
        raise RuntimeError(result[1]) 

從docs.python.org:

This example shows how to remove a directory tree on Windows where
some of the files have their read-only bit set. It uses the onerror
callback to clear the readonly bit and reattempt the remove. 
import os, stat
import shutil
 
def remove_readonly(func, path, _):
   "Clear the readonly bit and reattempt the removal"
    os.chmod(path, stat.S_IWRITE)
    func(path)
 
shutil.rmtree(directory, onerror=remove_readonly) 

在刪除之前檢查資料夾是否存在,這樣更可靠。

import shutil
def remove_folder(path):
    # check if folder exists
    if os.path.exists(path):
         # remove if exists
         shutil.rmtree(path)
    else:
         # throw your exception to handle this special scenario
         raise XXError("your exception")
remove_folder("/folder_name")

如果您不想使用shutil模組,可以只使用os模組。

from os import listdir, rmdir, remove
for i in listdir(directoryToRemove):
    os.remove(os.path.join(directoryToRemove, i))
rmdir(directoryToRemove) # Now the directory is empty of files
 
def deleteDir(dirPath):
    deleteFiles = []
    deleteDirs = []
    for root, dirs, files in os.walk(dirPath):
        for f in files:
            deleteFiles.append(os.path.join(root, f))
        for d in dirs:
            deleteDirs.append(os.path.join(root, d))
    for f in deleteFiles:
        os.remove(f)
    for d in deleteDirs:
        os.rmdir(d)
    os.rmdir(dirPath) 

為了簡單起見,可以使用os.system命令:

import os
os.system("rm -rf dirname")

很明顯,它實際上呼叫系統終端來完成這個任務。

刪除一個資料夾,即使它可能不存在(避免了Charles Chow的答案中的競爭條件),但當其他事情出錯時仍有錯誤(例如許可權問題、磁碟讀取錯誤、檔案不是目錄)
對於Python 3 .x:

import shutil
 
def ignore_absent_file(func, path, exc_inf):
    except_instance = exc_inf[1]
    if isinstance(except_instance, FileNotFoundError):
        return
    raise except_instance
 
shutil.rmtree(dir_to_delete, onerror=ignore_absent_file) 

透過os.walk,我將提出由3個一行程式python呼叫組成的解決方案:

python -c"import sys; import os; [os.chmod(os.path.join(rs,d), 0o777) for rs,ds,fs in os.walk(_path_) for d in ds]"
python -c"import sys; import os; [os.chmod(os.path.join(rs,f), 0o777) for rs,ds,fs in os.walk(_path_) for f in fs]"
python -c"import os; import shutil; shutil.rmtree(_path_, ignore_errors=False)" 

第一個指令碼chmod的所有子目錄,第二個指令碼chmod的所有檔案。然後,第三個指令碼會毫無障礙地刪除所有內容。
我在Jenkins工作中的"shell指令碼"中對此進行了測試(我不想將新的python指令碼儲存到SCM中,這就是為什麼搜尋單行解決方案),它適用於Linux和Windows。

使用python 3.7和linux仍然有不同的方法:

import subprocess
from pathlib import Path
#學習中遇到問題沒人解答?小編建立了一個Python學習交流群:711312441
 
#using pathlib.Path
path = Path('/path/to/your/dir')
subprocess.run(["rm","-rf", str(path)])
 
#using strings
path ="/path/to/your/dir"
subprocess.run(["rm","-rf", path]) 

本質上,它使用python的子程序模組來執行bash指令碼$ rm -rf '/path/to/your/dir,就好像使用終端來完成相同的任務一樣。它不是完全的python,但它可以完成。

我將pathlib.Path示例包括在內的原因是,根據我的經驗,它在處理許多變化的路徑時非常有用。匯入pathlib.Path模組並將最終結果轉換為字串的額外步驟對於我的開發時間來說通常會降低成本。如果Path.rmdir()帶有一個arg選項來顯式處理非空的dir,那就方便了。

對於Windows,如果目錄不是空的,並且您有隻讀檔案,或者收到如下錯誤:

Access is denied
The process cannot access the file because it is being used by another process

試試這個,os.system('rmdir /S /Q"{}"'.format(directory))。
它相當於Linux/Mac中的rm -rf。

我找到了一種非常簡單的方法來刪除Windows作業系統上的任何資料夾(甚至不是空的)或檔案。

os.system('powershell.exe  rmdir -r D:\workspace\Branches\*%s* -Force' %CANDIDATE_BRANCH)

相關文章