Hoe verwijder/verwijder ik een map die niet leeg is?

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 rmtreein 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 ptheen pathlib.Pathinstantie 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 Pathbestelbaar 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 pathlibbelooft 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/diruit 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.Pathheb 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.Pathen 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 shutilniet wilt gebruiken, kunt u gewoon de module osgebruiken.

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 -rfin 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)
        # -------------------------------------------------------------------------------------

Other episodes