[英]How do I remove/delete a folder that is not empty?
當我嘗試刪除非空文件夾時,出現“訪問被拒絕”錯誤。 我在嘗試中使用了以下命令: os.remove("/folder_name")
。
刪除/刪除非空文件夾/目錄的最有效方法是什么?
import shutil
shutil.rmtree('/folder_name')
按照設計, rmtree
在包含只讀文件的文件夾樹上失敗。 如果您希望刪除文件夾而不管它是否包含只讀文件,然后使用
shutil.rmtree('/folder_name', ignore_errors=True)
來自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))
import shutil
shutil.rmtree(dest, ignore_errors=True)
從 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 the dir content but not the dir itself, remove this line
其中pth
是pathlib.Path
實例。 不錯,但可能不是最快的。
來自docs.python.org :
此示例說明如何在 Windows 上刪除目錄樹,其中某些文件設置了只讀位。 它使用 onerror 回調清除只讀位並重新嘗試刪除。 任何后續失敗都會傳播。
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 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_info 是 sys.exc_info() 返回的元組。 如果 ignore_errors 為 false 且 onerror 為 None,則會引發異常。在此處輸入代碼
根據 kkubasik 的回答,在刪除之前檢查文件夾是否存在,更健壯
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")
我想添加一個“純路徑庫”方法:
from pathlib import Path
from typing import Union
def del_dir(target: Union[Path, str], only_if_empty: bool = False):
"""
Delete a given directory and its subdirectories.
:param target: The directory to delete
:param only_if_empty: Raise RuntimeError if any file is found in the tree
"""
target = Path(target).expanduser()
assert target.is_dir()
for p in sorted(target.glob('**/*'), reverse=True):
if not p.exists():
continue
p.chmod(0o666)
if p.is_dir():
p.rmdir()
else:
if only_if_empty:
raise RuntimeError(f'{p.parent} is not empty!')
p.unlink()
target.rmdir()
這依賴於Path
是可排序的,較長的路徑總是排在較短的路徑之后,就像str
一樣。 因此,目錄將位於文件之前。 如果我們顛倒排序,文件將出現在它們各自的容器之前,所以我們可以簡單地一次一個地取消鏈接/ rmdir它們。
好處:
pathlib
在 Python 3.6 中所承諾的;上面沒有說明不能在 Windows 上運行的操作)只需一些 python 3.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:] == '\n': 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])
十年后,使用 Python 3.7 和 Linux 仍然有不同的方法可以做到這一點:
import subprocess
from pathlib import Path
#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 的 subprocess 模塊來運行 bash 腳本$ rm -rf '/path/to/your/dir
,就好像您使用終端來完成相同的任務一樣。 它不是完全的 Python,但它完成了它。
我包含pathlib.Path
示例的原因是因為根據我的經驗,它在處理許多變化的路徑時非常有用。 導入pathlib.Path
模塊並將最終結果轉換為字符串的額外步驟對我來說通常會降低開發時間的成本。 如果Path.rmdir()
帶有一個 arg 選項來顯式處理非空目錄,那將會很方便。
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)
如果你不想使用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
刪除一個文件夾,即使它可能不存在(避免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)
Python 2.7 代碼幾乎相同:
import shutil
import errno
def ignore_absent_file(func, path, exc_inf):
except_instance = exc_inf[1]
if isinstance(except_instance, OSError) and \
except_instance.errno == errno.ENOENT:
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。
對於 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
。
基於遞歸的純pathlib
解決方案:
from pathlib import Path
def remove_path(path: Path):
if path.is_file() or path.is_symlink():
path.unlink()
return
for p in path.iterdir():
remove_path(p)
path.rmdir()
支持 Windows 和符號鏈接
為簡單起見,您可以使用 os.system 命令:
import os
os.system("rm -rf dirname")
很明顯,它實際上調用了系統終端來完成這個任務。
我找到了一種非常簡單的方法來刪除WINDOWS OS上的任何文件夾(甚至不是空的)或文件。
os.system('powershell.exe rmdir -r D:\workspace\Branches\*%s* -Force' %CANDIDATE_BRANCH)
在我的情況下,刪除的唯一方法是使用所有可能性,因為我的代碼應該由 cmd.exe 或 powershell.exe 運行。 如果是您的情況,只需使用此代碼創建一個函數即可:
#!/usr/bin/env python3
import shutil
from os import path, system
import sys
# Try to delete the folder ---------------------------------------------
if (path.isdir(folder)):
shutil.rmtree(folder, ignore_errors=True)
if (path.isdir(folder)):
try:
system("rd -r {0}".format(folder))
except Exception as e:
print("WARN: Failed to delete => {0}".format(e),file=sys.stderr)
if (path.isdir(self.backup_folder_wrk)):
try:
system("rd /s /q {0}".format(folder))
except Exception as e:
print("WARN: Failed to delete => {0}".format(e),file=sys.stderr)
if (path.isdir(folder)):
print("WARN: Failed to delete {0}".format(folder),file=sys.stderr)
# -------------------------------------------------------------------------------------
您可以嘗試以下代碼來刪除文件或文件夾,無論它們是空的還是非空的。
import shutil
import os
directory = "path/to/the/root/folder"
files_in_directory = os.listdir(directory)
for file in files_in_directory:
try:
path_to_file_or_folder = os.path.join(directory, file)
shutil.rmtree(path_to_file_or_folder)
except:
os.unlink(path_to_file_or_folder)
它有助於刪除包含所有文件和文件夾的目錄
import os
def rrmdir(path):
for entry in os.scandir(path):
if entry.is_dir():
rrmdir(entry)
else:
os.remove(entry)
os.rmdir(path)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.