Excluindo pastas em python recursivamente

203

Estou tendo um problema ao excluir diretórios vazios. Aqui está o meu código:

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

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

O argumento dir_to_searché onde estou passando o diretório onde o trabalho precisa ser feito. Esse diretório fica assim:

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

Observe que todas as pastas acima estão vazias. Quando executo esse script nas pastas 20, 25sozinho é excluído! Mas as pastas 25e 26não são excluídos, mesmo que eles são pastas vazias.

Editar:

A exceção que estou recebendo são:

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

Onde estou cometendo um erro?

sriram
fonte
1
tem certeza de que eles não têm arquivos ocultos?
29412 Jeff
Uma exceção ou traceback é impressa? Em caso afirmativo - ajudaria se você adicionasse isso à pergunta
Ngure Nyaga
@ Jeff: Sim, eu tenho certeza. Na verdade, na minha máquina ubuntu, tentei rmdir /path/to/25th/folderexcluir todo o diretório. O que significa que o diretório é um diretório vazio!
Srirev
2
Possível duplicata de Como remover / excluir uma pasta que não está vazia no Python? de pergunta e resposta #
Trevor Boyd Smith

Respostas:

392

Tente shutil.rmtree:

import shutil
shutil.rmtree('/path/to/your/dir/')
Tomek
fonte
5
O rmtreediretório inteiro foi excluído? Eu acho que é semelhante ao umrm -Rf $DIR
sriram
7
Tenha cuidado, pois o rmtree também exclui os arquivos. Como solicitado, a questão era como excluir docs directories.The vazio para os.walk dar um exemplo que quase corresponde exatamente esta pergunta: import os for root, dirs, files in os.walk(top, topdown=False): for name in dirs: os.rmdir(os.path.join(root, name))
DaveSawyer
Documentação da versão do Python3: docs.python.org/3/library/shutil.html#shutil.rmtree
Vladimir Oprya
27

O comportamento padrão de os.walk()é andar da raiz para a folha. Situado topdown=Falseno os.walk()andar de folha em raiz.

lqs
fonte
18

Aqui está o meu pathlibdesvinculador de diretório 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
fonte
12

Tente rmtree()em shutilda biblioteca padrão do Python

microo8
fonte
1
O rmtreediretório inteiro foi excluído? Eu acho que é semelhante ao umrm -Rf $DIR
sriram
2
from docs: "Exclua uma árvore de diretórios inteira; o caminho deve apontar para um diretório (mas não um link simbólico para um diretório). Se ignore_errors for verdadeiro, os erros resultantes de remoções com falha serão ignorados; se falsos ou omitidos, esses erros serão tratados chamando um manipulador especificado por onerror ou, se isso for omitido, eles geram uma exceção ".
microo8
7

melhor usar o caminho absoluto e importar apenas a função rmtree, from shutil import rmtree pois este é um pacote grande. A linha acima importará apenas a função necessária.

from shutil import rmtree
rmtree('directory-absolute-path')
Gajender
fonte
1
Você referencia isso como rmtree(); nãoshutil.rmtree()
Kevin Murphy
4

Apenas para o próximo cara que procura uma solução micropython, isso funciona puramente com base no os (listdir, remove, rmdir). Não é completo (especialmente no tratamento de erros) nem sofisticado, mas funcionará na maioria das circunstâncias.

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
fonte
3

O comando (fornecido por Tomek) não pode excluir um arquivo, se for somente leitura . portanto, pode-se 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
fonte
2
ao tentar o seu código com a minha própria pasta a ser excluído, eu recebo um erro dizendo: NameError: name 'stat' is not defined. Como foi definido?
Nnako 30/07/19
1
O módulo stat define constantes e funções para interpretar os resultados de os.stat (), os.fstat () e os.lstat (). o que você pode tentar: import os, sys de importação de estatísticas *
Monir
0

Aqui está outra solução pure-pathlib , mas sem recursão:

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
fonte
-1

Aqui está uma solução 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
fonte
-1

Para usuários do Linux, você pode simplesmente executar o comando shell de maneira pitônica

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

onde rmestá para remover e -rpara recursivamente

Garvit
fonte