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?


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

Respuestas:


392

Prueba shutil.rmtree:

import shutil
shutil.rmtree('/path/to/your/dir/')

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


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.


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/"))

12

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


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')

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)

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)

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()

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

-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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.