Eliminar carpetas en python de forma recursiva

203

Tengo un problema al eliminar directorios vacíos. Aquí está mi código:

for dirpath, dirnames, filenames in os.walk(dir_to_search):
    //other codes

    try:
        os.rmdir(dirpath)
    except OSError as ex:
        print(ex)

El argumento dir_to_searches donde paso el directorio donde se debe hacer el trabajo. Ese directorio se ve así:

test/20/...
test/22/...
test/25/...
test/26/...

Tenga en cuenta que todas las carpetas anteriores están vacías. Cuando ejecuto este script las carpetas 20, 25solo se elimina! Pero las carpetas 25y 26no se eliminan, a pesar de que son carpetas vacías.

Editar:

La excepción que estoy recibiendo son:

[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/29'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/29/tmp'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/28'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/28/tmp'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/26'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/25'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/27'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/27/tmp'

¿Dónde estoy cometiendo un error?

sriram
fuente
1
¿estás seguro de que no tienen archivos ocultos?
Jeff
¿Se imprime una excepción o rastreo? Si es así, sería útil si agregaras eso a la pregunta
Ngure Nyaga
@ Jeff: Sí, estoy seguro. De hecho, en mi máquina ubuntu, intenté rmdir /path/to/25th/foldereliminar todo el directorio. ¡Lo que significa que ese directorio está vacío!
sriram
2
Posible duplicado de ¿Cómo elimino / elimino una carpeta que no está vacía con Python? de ambas preguntas Y respuestas
Trevor Boyd Smith

Respuestas:

392

Prueba shutil.rmtree:

import shutil
shutil.rmtree('/path/to/your/dir/')
Tomek
fuente
55
¿ rmtreeEliminó todo el directorio? Supongo que es similar al unorm -Rf $DIR
sriram
77
Tenga cuidado ya que rmtree también elimina los archivos. Como se le preguntó, la pregunta era cómo eliminar directorios VACÍOS. Los documentos para os.walk dan un ejemplo que coincide casi exactamente con esta pregunta: import os for root, dirs, files in os.walk(top, topdown=False): for name in dirs: os.rmdir(os.path.join(root, name))
DaveSawyer
Documentos de la versión de Python3: docs.python.org/3/library/shutil.html#shutil.rmtree
Vladimir Oprya
27

El comportamiento predeterminado de os.walk()es caminar de raíz a hoja. Establecer topdown=Falseen os.walk()caminar desde la hoja hasta la raíz.

lqs
fuente
18

Aquí está mi pathlibdesvinculador de directorio recursivo puro :

from pathlib import Path

def rmdir(directory):
    directory = Path(directory)
    for item in directory.iterdir():
        if item.is_dir():
            rmdir(item)
        else:
            item.unlink()
    directory.rmdir()

rmdir(Path("dir/"))
mitch
fuente
12

Trate rmtree()de shutilde la biblioteca estándar de Python

microo8
fuente
1
¿ rmtreeEliminó todo el directorio? Supongo que es similar al unorm -Rf $DIR
sriram
2
de documentos: "Eliminar un árbol de directorios completo; la ruta debe apuntar a un directorio (pero no un enlace simbólico a un directorio). Si ignore_errors es verdadero, los errores resultantes de eliminaciones fallidas serán ignorados; si son falsos u omitidos, dichos errores se manejan llamando a un controlador especificado por onerror o, si se omite, generan una excepción ".
microo8
7

es mejor usar la ruta absoluta e importar solo la función rmtree from shutil import rmtree ya que este es un paquete grande, la línea anterior solo importará la función requerida.

from shutil import rmtree
rmtree('directory-absolute-path')
Gajender
fuente
1
Entonces, haría referencia a esto como rmtree(); noshutil.rmtree()
Kevin Murphy
4

Solo para el próximo tipo que busca una solución de micropython, esto funciona puramente basado en os (listdir, remove, rmdir). No es completo (especialmente en el manejo de errores) ni elegante, sin embargo, funcionará en la mayoría de las circunstancias.

def deltree(target):
    print("deltree", target)
    for d in os.listdir(target):
        try:
            deltree(target + '/' + d)
        except OSError:
            os.remove(target + '/' + d)

    os.rmdir(target)
Justus Wingert
fuente
3

El comando (dado por Tomek) no puede eliminar un archivo, si es de solo lectura . por lo tanto, uno puede usar -

import os, sys
import stat

def del_evenReadonly(action, name, exc):
    os.chmod(name, stat.S_IWRITE)
    os.remove(name)

if  os.path.exists("test/qt_env"):
    shutil.rmtree('test/qt_env',onerror=del_evenReadonly)
Monir
fuente
2
cuando se trata de su código con mi propia carpeta que desea eliminar, me sale un error que dice: NameError: name 'stat' is not defined. ¿Cómo se ha definido?
nnako
1
El módulo stat define constantes y funciones para interpretar los resultados de os.stat (), os.fstat () y os.lstat (). lo que puedes probar: importar os, sys desde stat import *
Monir
0

Aquí hay otra solución de pathlib puro , pero sin recurrencia:

from pathlib import Path
from typing import Union

def del_empty_dirs(base: Union[Path, str]):
    base = Path(base)
    for p in sorted(base.glob('**/*'), reverse=True):
        if p.is_dir():
            p.chmod(0o666)
            p.rmdir()
        else:
            raise RuntimeError(f'{p.parent} is not empty!')
    base.rmdir()
pepoluan
fuente
-1

Aquí hay una solución recursiva:

def clear_folder(dir):
    if os.path.exists(dir):
        for the_file in os.listdir(dir):
            file_path = os.path.join(dir, the_file)
            try:
                if os.path.isfile(file_path):
                    os.unlink(file_path)
                else:
                    clear_folder(file_path)
                    os.rmdir(file_path)
            except Exception as e:
                print(e)
Tobias Ernst
fuente
-1

Para usuarios de Linux, simplemente puede ejecutar el comando de shell de una manera pitónica

import os
os.system("rm -r /home/user/folder_name")

donde rmse alza para quitar y -rpara de forma recursiva

Garvit
fuente