Ik krijg de foutmelding ‘toegang is geweigerd’ wanneer ik probeer een map te verwijderen die niet leeg is. Ik gebruikte het volgende commando in mijn poging: os.remove("/folder_name")
.
Wat is de meest effectieve manier om een map/directory die niet leeg is te verwijderen/verwijderen?
Antwoord 1, autoriteit 100%
import shutil
shutil.rmtree('/folder_name')
Standaardbibliotheekreferentie: shutil.rmtree.
Door het ontwerp faalt rmtree
in mapstructuren die alleen-lezen bestanden bevatten. Als u wilt dat de map wordt verwijderd, ongeacht of deze alleen-lezen bestanden bevat, gebruik dan
shutil.rmtree('/folder_name', ignore_errors=True)
Antwoord 2, autoriteit 10%
Van de python-documentenop os.walk()
:
# 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))
Antwoord 3, autoriteit 8%
import shutil
shutil.rmtree(dest, ignore_errors=True)
Antwoord 4, autoriteit 2%
vanaf python 3.4 mag je gebruiken:
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
waarbij pth
een pathlib.Path
instantie is. Leuk, maar misschien niet de snelste.
Antwoord 5
Van docs.python.org:
Dit voorbeeld laat zien hoe u een directorystructuur op Windows verwijdert waar
sommige bestanden hebben hun alleen-lezen bitset. Het gebruikt de fout
callback om het alleen-lezen bit te wissen en het verwijderen opnieuw te proberen. Elk
volgende mislukking zal zich verspreiden.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)
Antwoord 6
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)
Als negeer_errors is ingesteld, worden fouten genegeerd; anders, als onerror is ingesteld, wordt het aangeroepen om de fout af te handelen met argumenten (func, path, exc_info) waarbij func os.listdir, os.remove of os.rmdir is; pad is het argument voor die functie waardoor deze faalde; en exc_info is een tuple die wordt geretourneerd door sys.exc_info(). Als negeer_errors onwaar is en de fout Geen is, wordt er een uitzondering gemaakt. Voer hier de code in
Antwoord 7
Gebaseerd op het antwoord van kkubasik, controleer of de map bestaat voordat u deze verwijdert, robuuster
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")
Antwoord 8
Slechts enkele python 3.5-opties om de bovenstaande antwoorden te voltooien. (Ik had ze hier graag gevonden).
import os
import shutil
from send2trash import send2trash # (shutil delete permanently)
Map verwijderen indien leeg
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")
Verwijder ook de map als deze dit bestand bevat
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)
verwijder de map als deze alleen .srt- of .txt-bestand(en) bevat
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")
Verwijder map als de grootte kleiner is dan 400 kb :
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")
Antwoord 9
Ik wil graag een “pure pathlib”-benadering toevoegen:
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()
Dit is afhankelijk van het feit dat Path
bestelbaar is, en langere paden zullen altijd worden gesorteerd op kortere paden, net als str
. Daarom komen mappen voor bestanden. Als we de sortering omkeren, komen bestanden voor hun respectievelijke containers, zodat we ze eenvoudig een voor een kunnen ontkoppelen/rmdireren met één doorgang.
Voordelen:
- Het is NIET afhankelijk van externe binaire bestanden: alles maakt gebruik van de met batterijen meegeleverde modules van Python (Python >= 3.6)
- Wat betekent dat het niet herhaaldelijk een nieuw subproces hoeft te starten om te ontkoppelen
- Het is vrij snel & eenvoudig; u hoeft uw eigen recursie niet te implementeren
- Het is platformonafhankelijk (tenminste, dat is wat
pathlib
belooft in Python 3.6; geen enkele bewerking hierboven vermeld om niet op Windows te draaien) - Indien nodig kan men een zeer gedetailleerde logging doen, bv. elke verwijdering loggen wanneer deze plaatsvindt.
Antwoord 10
Als je er zeker van bent dat je de hele dir-tree wilt verwijderen en niet meer geïnteresseerd bent in de inhoud van dir, dan is het domheid om naar de hele dir-boom te kruipen… bel daarvoor gewoon het native OS-commando van python. Het zal sneller, efficiënter en minder geheugengebruik zijn.
RMDIR c:\blah /s /q
of *nix
rm -rf /home/whatever
In python ziet de code eruit als…
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])
Antwoord 11
Tien jaar later en met Python 3.7 en Linux zijn er nog steeds verschillende manieren om dit te doen:
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])
In wezen gebruikt het de subprocesmodule van Python om het bash-script $ rm -rf '/path/to/your/dir
uit te voeren alsof je de terminal gebruikt om dezelfde taak uit te voeren. Het is niet volledig Python, maar het klaart het.
De reden dat ik het voorbeeld pathlib.Path
heb opgenomen, is omdat het in mijn ervaring erg handig is bij het omgaan met veel paden die veranderen. De extra stappen van het importeren van de module pathlib.Path
en het converteren van de eindresultaten naar strings zijn voor mij vaak een lagere ontwikkeltijd. Het zou handig zijn als Path.rmdir()
een arg-optie zou hebben om niet-lege mappen expliciet af te handelen.
Antwoord 12
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)
Antwoord 13
Als u de module shutil
niet wilt gebruiken, kunt u gewoon de module os
gebruiken.
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
Antwoord 14
Om een map te verwijderen, zelfs als deze niet bestaat (waarbij de race-conditie wordt vermeden in Charles Chow’s antwoord) maar heeft nog steeds fouten wanneer andere dingen fout gaan (bijvoorbeeld toestemmingsproblemen, schijfleesfout, het bestand is geen map)
Voor 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)
De Python 2.7-code is bijna hetzelfde:
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)
Antwoord 15
Met os.walk zou ik de oplossing voorstellen die bestaat uit 3 one-liner Python-aanroepen:
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)"
Het eerste script chmod bevat alle submappen, het tweede script chmod bevat alle bestanden. Dan verwijdert het derde script alles zonder belemmeringen.
Ik heb dit getest vanuit het “Shell-script” in een Jenkins-taak (ik wilde geen nieuw Python-script in SCM opslaan, daarom zocht ik naar een éénregelige oplossing) en het werkte voor Linux en Windows.
Antwoord 16
Voor Windows, als de map niet leeg is en je alleen-lezen bestanden hebt of als je fouten krijgt zoals
Access is denied
The process cannot access the file because it is being used by another process
Probeer dit, os.system('rmdir /S /Q "{}"'.format(directory))
Het is equivalent voor rm -rf
in Linux/Mac.
Antwoord 17
Op recursie gebaseerde, pure pathlib
-oplossing:
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()
Ondersteunt Windows en symbolische links
Antwoord 18
Je kunt voor de eenvoud de opdracht os.system gebruiken:
import os
os.system("rm -rf dirname")
Zoals voor de hand liggend, roept het in feite de systeemterminal op om deze taak te volbrengen.
Antwoord 19
Ik heb een heel gemakkelijke manier gevonden om een map (zelfs NIET leeg)of bestand op WINDOWS OSte verwijderen.
os.system('powershell.exe rmdir -r D:\workspace\Branches\*%s* -Force' %CANDIDATE_BRANCH)
Antwoord 20
In mijn geval was de enige manier om te verwijderen door alle mogelijkheden te gebruiken, omdat mijn code moest worden uitgevoerd door cmd.exe of powershell.exe. Als het jouw geval is, maak dan gewoon een functie met deze code en het komt goed:
#!/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)
# -------------------------------------------------------------------------------------