Come eliminare il contenuto di una cartella?


470

Come posso eliminare il contenuto di una cartella locale in Python?

Il progetto attuale è per Windows, ma vorrei vedere anche * nix.


2
per * nix ad essere onesti vorrei solo usareos.system('rm -rf folder')
Tilak Maddy

Risposte:


444
import os, shutil
folder = '/path/to/folder'
for filename in os.listdir(folder):
    file_path = os.path.join(folder, filename)
    try:
        if os.path.isfile(file_path) or os.path.islink(file_path):
            os.unlink(file_path)
        elif os.path.isdir(file_path):
            shutil.rmtree(file_path)
    except Exception as e:
        print('Failed to delete %s. Reason: %s' % (file_path, e))

4
Se stai lavorando con una directory molto grande, e in particolare una directory di rete su Windows, e puoi controllare l'ambiente in cui viene eseguito questo programma, potrebbe valere la pena usare la funzione "os.scandir (cartella)" di Py3.5 invece di listdir. La sintassi è abbastanza diversa dopo, ma piuttosto semplice da implementare; felice di pubblicarlo se altri lo desiderano.
Michael Scott Cuthbert,

Ricevo un avviso di pylint con le except Exception as e:letture W0703: Catching too general exception Exception. Esiste un'eccezione più specifica da rilevare o devo ignorarla?
John Hany,

7
@JohnHany, credo che tu voglia catturare OSError.
MikeB,

246

Puoi semplicemente farlo:

import os
import glob

files = glob.glob('/YOUR/PATH/*')
for f in files:
    os.remove(f)

Ovviamente puoi usare un altro filtro nel tuo percorso, ad esempio: /YOU/PATH/*.txt per rimuovere tutti i file di testo in una directory.


12
@Blueicefield *non elencherà i file nascosti, dovremmo anche aggiungereglob.glob('path/.*)
satoru

5
anche se per cancellare la lista dei file, mi sembra più semplice fare:import sh; sh.rm(files)
Robin Winslow,

2
Anche import sh; sh.rm(files)se sembra più bello, ci sono problemi se ci sono più di 1024 file nella directory.
Eugene,

235

Puoi eliminare la cartella stessa, così come tutto il suo contenuto, usando shutil.rmtree:

import shutil
shutil.rmtree('/path/to/folder')
shutil.rmtree(path, ignore_errors=False, onerror=None)


Elimina un intero albero di directory; il percorso deve puntare a una directory (ma non un collegamento simbolico a una directory). Se ignore_errors è true, gli errori risultanti da rimozioni non riuscite verranno ignorati; se falsi o omessi, tali errori vengono gestiti chiamando un gestore specificato da onerror o, se viene omesso, generano un'eccezione.


270
Questo non solo eliminerà il contenuto ma anche la cartella stessa. Non penso sia la domanda.
Iker Jimenez,

3
Penso che sia una buona risposta. Perché non elimini solo i contenuti e la cartella e quindi rifai la cartella?
cssndrx,

42
Perché la nuova directory e quella vecchia non saranno le stesse. Quindi, se un programma è seduto nella directory, in attesa di cose, avrà il tappeto estratto da sotto di esso.
Mike Cooper,

30
Basta ricreare la directory dopo rmtree. Comeos.makedirs(dir)
Iulius Curt il

3
@IuliusCurt no, ho una directory montata in ram che devo svuotare, e sfortunatamente non posso semplicemente cancellarla e poi ricrearla:OSError: [Errno 16] Device or resource busy
Arnaud P

80

Espandendo la risposta di mhawke questo è ciò che ho implementato. Rimuove tutto il contenuto di una cartella ma non la cartella stessa. Testato su Linux con file, cartelle e collegamenti simbolici, dovrebbe funzionare anche su Windows.

import os
import shutil

for root, dirs, files in os.walk('/path/to/folder'):
    for f in files:
        os.unlink(os.path.join(root, f))
    for d in dirs:
        shutil.rmtree(os.path.join(root, d))

1
Perché 'camminare' e non solo elencare il contenuto della cartella?
Don

2
Questa è la risposta corretta se si desidera eliminare anche le directory. walkviene utilizzato per dividere dirs vs file, che devono essere gestiti in modo diverso. Potresti anche usare os.listdir, ma dovresti controllare se ogni voce è una directory o un file manualmente.
dkamins,

7
Questo è vicino, ma sia os.walk che shutil.rmtree sono ricorsivi. os.walk non è necessario poiché è necessario pulire solo i file e le directory di livello superiore all'interno della directory. Basta usare un'istruzione if sugli elementi in os.listdir per vedere se ognuno è un file o una directory. Quindi utilizzare remove / unlink e rmtree rispettivamente.
Matthew Alpert,

1
@MatthewAlpert Nota, tuttavia, che os.walknon verrà ripreso qui, perché restituisce un generatore che esamina ricorsivamente le sottodirectory solo quando provi ad avanzare, e quando hai eseguito la prima iterazione di questo ciclo, non ci sono sottodirectory lasciato a guardare. In sostanza, os.walkviene usato qui solo come un modo alternativo di distinguere le cartelle di livello superiore dai file di livello superiore; la ricorsione non viene utilizzata e non paghiamo alcun costo di performance. È eccentrico, tuttavia, e concordo sul fatto che l'approccio che suggerisci è migliore semplicemente perché è più esplicito e leggibile.
Mark Amery,

47

L'uso rmtreee la ricreazione della cartella potrebbe funzionare, ma ho riscontrato errori durante l'eliminazione e la ricostruzione immediata delle cartelle sulle unità di rete.

La soluzione proposta utilizzando walk non funziona in quanto utilizza rmtreeper rimuovere le cartelle e quindi può tentare di utilizzare os.unlinki file che erano in precedenza in tali cartelle. Questo provoca un errore.

La globsoluzione pubblicata tenterà inoltre di eliminare cartelle non vuote, causando errori.

Ti suggerisco di usare:

folder_path = '/path/to/folder'
for file_object in os.listdir(folder_path):
    file_object_path = os.path.join(folder_path, file_object)
    if os.path.isfile(file_object_path) or os.path.islink(file_object_path):
        os.unlink(file_object_path)
    else:
        shutil.rmtree(file_object_path)

1
La soluzione genererà inoltre un errore se è presente un collegamento simbolico a un'altra directory.
Blueicefield,

@Blueicefield - Puoi fornire un esempio. Ho provato su Linux usando un file e una cartella con collegamento simbolico e non sono ancora riuscito a causare un errore.
jgoeders,

@jgoeders - Se c'è un link simbolico a una directory, os.path.isfile()tornerà False(perché segue i link simbolici) e finirai per chiamare shutil.rmtree()un link simbolico, che aumenterà OSError("Cannot call rmtree on a symbolic link").
Rockallite,

1
@Rockallite risolto con assegno a islink
kevinf

1
Inoltre: @kevinf ha ragione a sottolineare la necessità di un islinkcontrollo qui per gestire correttamente i collegamenti simbolici alle directory. Ho aggiunto un tale assegno alla risposta accettata.
Mark Amery,

20

Questo:

  • rimuove tutti i collegamenti simbolici
    • collegamenti morti
    • collegamenti alle directory
    • collegamenti ai file
  • rimuove le sottodirectory
  • non rimuove la directory principale

Codice:

for filename in os.listdir(dirpath):
    filepath = os.path.join(dirpath, filename)
    try:
        shutil.rmtree(filepath)
    except OSError:
        os.remove(filepath)

Come molte altre risposte, questo non tenta di regolare le autorizzazioni per consentire la rimozione di file / directory.


15

Come oneliner:

import os

# Python 2.7
map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )

# Python 3+
list( map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) ) )

Una soluzione più solida che tiene conto anche di file e directory (2.7):

def rm(f):
    if os.path.isdir(f): return os.rmdir(f)
    if os.path.isfile(f): return os.unlink(f)
    raise TypeError, 'must be either file or directory'

map( rm, (os.path.join( mydir,f) for f in os.listdir(mydir)) )

1
per operazioni di grandi dimensioni l'utilizzo del generatore può essere frazionalmente più efficientemap( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
user25064

effettivamente cercando di usarlo, list(map(os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir))))
ho

Il primo incluso nella risposta, il secondo non ha senso per me. Perché dovresti iterare su una funzione mappata su un iterabile? La mappa lo fa.
Fmonegaglia,

1
In python3, bisogna avvolgere mapin list realmente iterare. Vedi http://stackoverflow.com/questions/1303347/getting-a-map-to-return-a-list-in-python-3-x
paulwasit

Questo sicuramente non funzionerà se 'mydir' contiene almeno una cartella, poiché unlink funziona solo per i file ...
kupsef

14

Note: nel caso in cui qualcuno abbia votato la mia risposta, ho qualcosa da spiegare qui.

  1. A tutti piacciono le risposte brevi e semplici. Tuttavia, a volte la realtà non è così semplice.
  2. Torna alla mia risposta So che shutil.rmtree()potrebbe essere usato per cancellare un albero di directory. L'ho usato molte volte nei miei progetti. Ma devi capire che anche la directory stessa verrà eliminata dashutil.rmtree() . Anche se questo potrebbe essere accettabile per alcuni, non è una risposta valida per eliminare il contenuto di una cartella (senza effetti collaterali) .
  3. Ti mostrerò un esempio degli effetti collaterali. Supponiamo di avere una directory con proprietari personalizzati e bit di modalità, in cui ci sono molti contenuti. Quindi lo elimini con shutil.rmtree()e lo ricostruisci con os.mkdir(). E otterrai invece una directory vuota con i proprietari (ereditati) predefiniti e bit di modalità. Mentre potresti avere il privilegio di eliminare il contenuto e persino la directory, potresti non essere in grado di ripristinare il proprietario originale e i bit della modalità nella directory (ad es. Non sei un superutente).
  4. Infine, sii paziente e leggi il codice . È lungo e brutto (in vista), ma dimostrato di essere affidabile ed efficiente (in uso).

Ecco una soluzione lunga e brutta, ma affidabile ed efficiente.

Risolve alcuni problemi che non vengono risolti dagli altri risponditori:

  • Gestisce correttamente i collegamenti simbolici, incluso il non chiamare shutil.rmtree()un collegamento simbolico (che supererà il os.path.isdir()test se si collega a una directory; anche il risultato dios.walk() contiene anche directory simboliche collegate).
  • Gestisce bene i file di sola lettura.

Ecco il codice (l'unica funzione utile è clear_dir()):

import os
import stat
import shutil


# http://stackoverflow.com/questions/1889597/deleting-directory-in-python
def _remove_readonly(fn, path_, excinfo):
    # Handle read-only files and directories
    if fn is os.rmdir:
        os.chmod(path_, stat.S_IWRITE)
        os.rmdir(path_)
    elif fn is os.remove:
        os.lchmod(path_, stat.S_IWRITE)
        os.remove(path_)


def force_remove_file_or_symlink(path_):
    try:
        os.remove(path_)
    except OSError:
        os.lchmod(path_, stat.S_IWRITE)
        os.remove(path_)


# Code from shutil.rmtree()
def is_regular_dir(path_):
    try:
        mode = os.lstat(path_).st_mode
    except os.error:
        mode = 0
    return stat.S_ISDIR(mode)


def clear_dir(path_):
    if is_regular_dir(path_):
        # Given path is a directory, clear its content
        for name in os.listdir(path_):
            fullpath = os.path.join(path_, name)
            if is_regular_dir(fullpath):
                shutil.rmtree(fullpath, onerror=_remove_readonly)
            else:
                force_remove_file_or_symlink(fullpath)
    else:
        # Given path is a file or a symlink.
        # Raise an exception here to avoid accidentally clearing the content
        # of a symbolic linked directory.
        raise OSError("Cannot call clear_dir() on a symbolic link")

Non capisco in quale contesto abbia senso cambiare la modalità file. Sul mio Mac, os.remove, a differenza del rmprogramma di utilità, è felice di cancellare i file di sola lettura finché li si possiede. Nel frattempo, se si tratta di un file di cui non si possiede l'accesso di sola lettura, non è possibile eliminarlo o modificarne le autorizzazioni. Non conosco alcuna situazione su nessun sistema in cui non saresti in grado di eliminare un file di sola lettura con la os.removepossibilità di modificarne le autorizzazioni. Inoltre, usi lchmod, che non esiste sul mio Mac, né su Windows secondo i suoi documenti. A quale piattaforma è destinato questo codice ?!
Mark Amery,

14

Sono sorpreso che nessuno abbia menzionato il fantastico pathlibfare questo lavoro.

Se vuoi solo rimuovere i file in una directory, può essere un oneliner

from pathlib import Path

[f.unlink() for f in Path("/path/to/folder").glob("*") if f.is_file()] 

Per rimuovere ricorsivamente anche le directory puoi scrivere qualcosa del genere:

from pathlib import Path
from shutil import rmtree

for path in Path("/path/to/folder").glob("**/*"):
    if path.is_file():
        path.unlink()
    elif path.is_dir():
        rmtree(path)

1
.iterdir()invece di .glob(...)dovrebbe funzionare anche.
S. Kirby,

12
import os
import shutil

# Gather directory contents
contents = [os.path.join(target_dir, i) for i in os.listdir(target_dir)]

# Iterate and remove each item in the appropriate manner
[os.remove(i) if os.path.isfile(i) or os.path.islink(i) else shutil.rmtree(i) for i in contents]

Un commento precedente menziona anche l'uso di os.scandir in Python 3.5+. Per esempio:

import os
import shutil

with os.scandir(target_dir) as entries:
    for entry in entries:
        if entry.is_file() or entry.is_symlink():
            os.remove(entry.path)
        elif entry.is_dir():
            shutil.rmtree(entry.path)

1
os.path.isdir()non è un modo valido per distinguere tra una directory normale e un collegamento simbolico. La chiamata shutil.rmtree()a un collegamento simbolico genererà OSErrorun'eccezione.
Rockallite,

@Rockallite Grazie. Hai ragione. Ho aggiornato l'esempio.
Jacob Wan,

8

Potrebbe essere meglio usarlo os.walk()per questo.

os.listdir()non distingue i file dalle directory e ti metterai rapidamente nei guai nel tentativo di scollegarli. C'è un buon esempio di come utilizzare os.walk()per rimuovere ricorsivamente una directory qui e suggerimenti su come adattarla alle circostanze.


6

Ho usato per risolvere il problema in questo modo:

import shutil
import os

shutil.rmtree(dirpath)
os.mkdir(dirpath)

7
Questo ha una semantica radicalmente diversa da quella che pone la domanda e non dovrebbe essere considerata una risposta valida.
Fatuhoku,

1
Con rispetto penso che "Elimina il contenuto della cartella locale" non comporta la rimozione della cartella stessa. Stesso problema di questa risposta , tranne per il fatto che uno ha ricevuto molti voti!
Fatuhoku,

3
È come rispondere alla domanda "Come faccio ad avere una funzione restituire il numero 1 in Python?" con def return_a_one (): launch_some_nukes () return 1
fatuhoku

2
Ovviamente la semantica è diversa: ma potresti anche considerarla come un altro modo di vedere il problema. Questa soluzione è perfettamente valida in quanto risolve il problema. C'è una differenza nell'esempio di 'launch_some_nukes': 1. La soluzione è più breve e più facile di quella accettata e contrariamente alla risposta che hai citato è valida. 2. l'equivalente 'launch_some_nukes' in questo caso sta eliminando e ricreando una cartella. La differenza tra la vecchia e la nuova cartella è solo il numero di inode (probabilmente irrilevante per l'OP)
ProfHase85

2
Sta piuttosto demolendo il grattacielo e ricostruendone esattamente le stesse dimensioni;)
ProfHase85

5

Ancora un'altra soluzione:

import sh
sh.rm(sh.glob('/path/to/folder/*'))

1
Nota che shnon fa parte della libreria standard e deve essere installato da PyPI prima di poterlo utilizzare. Inoltre, poiché in realtà questo invoca rmin un sottoprocesso, non funzionerà su Windows dove rmnon esiste. Inoltre genererà un'eccezione se la cartella contiene delle sottodirectory.
Mark Amery,

5

So che è un vecchio thread ma ho trovato qualcosa di interessante dal sito ufficiale di Python. Solo per condividere un'altra idea per la rimozione di tutti i contenuti in una directory. Perché ho alcuni problemi di autorizzazione quando uso shutil.rmtree () e non voglio rimuovere la directory e ricrearla. L'indirizzo originale è http://docs.python.org/2/library/os.html#os.walk . Spero che possa aiutare qualcuno.

def emptydir(top):
    if(top == '/' or top == "\\"): return
    else:
        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))

4

Per eliminare tutti i file all'interno della directory e le relative sottodirectory, senza rimuovere le cartelle stesse, è sufficiente:

import os
mypath = "my_folder" #Enter your path here
for root, dirs, files in os.walk(mypath):
    for file in files:
        os.remove(os.path.join(root, file))

3

Se si utilizza un sistema * nix, perché non sfruttare il comando di sistema?

import os
path = 'folder/to/clean'
os.system('rm -rf %s/*' % path)

3
Perché, come affermato nella domanda, "Il progetto attuale è per Windows"
sox con Monica il

3

Modo abbastanza intuitivo per farlo:

import shutil, os


def remove_folder_contents(path):
    shutil.rmtree(path)
    os.makedirs(path)


remove_folder_contents('/path/to/folder')

3

Bene, penso che questo codice funzioni. Non eliminerà la cartella ed è possibile utilizzare questo codice per eliminare i file con l'estensione specifica.

import os
import glob

files = glob.glob(r'path/*')
for items in files:
    os.remove(items)

3

Ho dovuto rimuovere i file da 3 cartelle separate all'interno di un'unica directory padre:

directory
   folderA
      file1
   folderB
      file2
   folderC
      file3

Questo semplice codice mi ha aiutato: (Sono su Unix)

import os
import glob

folders = glob.glob('./path/to/parentdir/*')
for fo in folders:
  file = glob.glob(f'{fo}/*')
  for f in file:
    os.remove(f)

Spero che sia di aiuto.


1

Ho risolto il problema rmtree makedirsaggiungendo time.sleep()tra:

if os.path.isdir(folder_location):
    shutil.rmtree(folder_location)

time.sleep(.5)

os.makedirs(folder_location, 0o777)

0

Rispondi per una situazione specifica limitata: supponendo che tu voglia eliminare i file mentre mantieni l'albero delle sottocartelle, potresti usare un algoritmo ricorsivo:

import os

def recursively_remove_files(f):
    if os.path.isfile(f):
        os.unlink(f)
    elif os.path.isdir(f):
        for fi in os.listdir(f):
            recursively_remove_files(os.path.join(f, fi))

recursively_remove_files(my_directory)

Forse leggermente fuori tema, ma penso che molti lo troverebbero utile


L'uso os.walknel modo mostrato su stackoverflow.com/a/54889532/1709587 è forse un modo migliore di eliminare tutti i file lasciando intatta la struttura delle directory.
Mark Amery,

-1

Supponendo temp_dirdi essere eliminato, un comando a riga singola che utilizza ossarebbe:

_ = [os.remove(os.path.join(save_dir,i)) for i in os.listdir(temp_dir)]

Nota: questa è solo una riga per l'eliminazione dei file 'Non elimina le directory.

Spero che sia di aiuto. Grazie.


-1

Utilizzare il metodo seguente per rimuovere il contenuto di una directory, non la directory stessa:

import os
import shutil

def remove_contents(path):
    for c in os.listdir(path):
        full_path = os.path.join(path, c)
        if os.path.isfile(full_path):
            os.remove(full_path)
        else:
            shutil.rmtree(full_path)

@FabioSpaghetti Negative
Amir Rezazadeh

grazie Amir, sto cercando una soluzione che trovi una determinata cartella in tutte le sottodirectory di una directory radice e rimuove il contenuto di quella cartella
FabioSpaghetti

Questo non aggiunge nulla di nuovo che non era già stato mostrato nella risposta accettata anni prima che tu lo pubblicassi.
Mark Amery,

-1

il modo più semplice per eliminare tutti i file in una cartella / rimuovere tutti i file

import os
files = os.listdir(yourFilePath)
for f in files:
    os.remove(yourFilePath + f)

Non ci sono se ci sono sottodirectory.
Mark Amery,

-3

Questo dovrebbe fare il trucco semplicemente usando il modulo OS per elencare e quindi rimuovere!

import os
DIR = os.list('Folder')
for i in range(len(DIR)):
    os.remove('Folder'+chr(92)+i)

Ha funzionato per me, qualsiasi problema fammi sapere!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.