Como excluir o conteúdo de uma pasta?

470

Como posso excluir o conteúdo de uma pasta local no Python?

O projeto atual é para Windows, mas eu gostaria de ver também * nix.

UnkwnTech
fonte
2
para * nix para ser honesto eu iria usar apenasos.system('rm -rf folder')
Tilak Maddy

Respostas:

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))
Nick Stinemates
fonte
4
Se você estiver trabalhando com um diretório muito grande, principalmente um diretório de rede no Windows, e conseguir controlar o ambiente em que esse programa é executado, pode valer a pena usar a função "os.scandir (pasta)" do Py3.5 em vez de listdir. A sintaxe é bem diferente depois disso, mas bastante simples de implementar; feliz em publicá-lo, se outros quiserem.
22716 Michael Jackson Cuthbert #
Estou recebendo um aviso de pylint com except Exception as e:isso W0703: Catching too general exception Exception. Existe uma exceção mais específica para capturar ou devo ignorá-la?
John Hany
7
@ JohnHany, acredito que você quer pegar o OSError.
MikeB
246

Você pode simplesmente fazer isso:

import os
import glob

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

Obviamente, você pode usar outro filtro no caminho, por exemplo: /YOU/PATH/*.txt para remover todos os arquivos de texto em um diretório.

Blueicefield
fonte
12
@Blueicefield *não lista oculta arquivos, devemos acrescentar tambémglob.glob('path/.*)
satoru
5
embora para excluir a lista de arquivos, parece mais simples para me fazer:import sh; sh.rm(files)
Robin Winslow
2
Embora import sh; sh.rm(files)pareça mais bonito, você terá problemas se houver mais de 1024 arquivos no diretório.
Eugene
235

Você pode excluir a própria pasta, bem como todo o seu conteúdo, usando shutil.rmtree:

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


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 falhas na remoção serão ignorados; se falso ou omitido, esses erros são tratados chamando um manipulador especificado por onerror ou, se isso for omitido, eles geram uma exceção.

Oli
fonte
270
Isso não apenas excluirá o conteúdo, mas também a própria pasta. Eu não acho que é o que a pergunta faz.
Iker Jimenez
3
Eu acho que é uma boa resposta. Por que você não exclui o conteúdo e a pasta e refaz a pasta?
Cssndrx 6/07
42
Porque o novo diretório e o antigo não serão os mesmos. Portanto, se um programa estiver no diretório, aguardando as coisas, ele terá o tapete retirado dele.
Mike Cooper
30
Apenas recrie o diretório depois rmtree. Comoos.makedirs(dir)
Iulius Curt
3
@IuliusCurt não, eu tenho um diretório montado no ram que eu preciso esvaziar e, infelizmente, não posso simplesmente excluir e depois recriá-lo:OSError: [Errno 16] Device or resource busy
Arnaud P
80

Expandir a resposta de mhawke é isso que eu implementei. Remove todo o conteúdo de uma pasta, mas não a própria pasta. Testado no Linux com arquivos, pastas e links simbólicos, também deve funcionar no 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))
Iker Jimenez
fonte
1
Por que 'andar' e não apenas listar o conteúdo da pasta?
Don
2
Esta é a resposta correta se você deseja excluir diretórios também. walké usado para dividir diretórios x arquivos, que devem ser tratados de maneira diferente. Você também pode usar os.listdir, mas precisará verificar se cada entrada é um diretório ou arquivo manualmente.
Dkamins 16/03/12
7
Isso está próximo, mas os.walk e shutil.rmtree são recursivos. o os.walk é desnecessário, pois você só precisa que os arquivos e diretórios no nível superior dentro do diretório sejam limpos. Basta usar uma instrução if nos elementos do os.listdir para ver se cada um é um arquivo ou diretório. Em seguida, use remover / desvincular e rmtree, respectivamente.
Matthew Alpert
1
@MatthewAlpert Note, no entanto, que os.walknão será repetido aqui, porque retorna um gerador que apenas recursivamente examina subdiretórios quando você tenta avançar e, quando você faz sua primeira iteração desse loop, não há subdiretórios esquerda para olhar. Em essência, os.walkestá apenas sendo usado aqui como uma maneira alternativa de distinguir pastas de nível superior dos arquivos de nível superior; a recursão não está sendo usada e não pagamos nenhum custo por desempenho. É excêntrico, no entanto, e concordo que a abordagem que você sugere é melhor simplesmente porque é mais explícita e legível.
Mark Amery
47

Usar rmtreee recriar a pasta pode funcionar, mas eu encontrei erros ao excluir e recriar imediatamente as pastas nas unidades de rede.

A solução proposta usando walk não funciona da mesma maneira que rmtreeremove pastas e, em seguida, pode tentar usar os.unlinkos arquivos que estavam anteriormente nessas pastas. Isso causa um erro.

A globsolução publicada também tentará excluir pastas não vazias, causando erros.

Eu sugiro que você use:

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)
jgoeders
fonte
1
Sua solução também gerará um erro se houver um link simbólico para outro diretório.
Blueicefield
@Blueicefield - Você pode fornecer um exemplo. Eu testei no linux usando um arquivo e uma pasta com link simbólico e ainda não consegui causar um erro.
jgoeders
@jgoeders - Se houver um link simbólico para um diretório, os.path.isfile()ele retornará False(porque segue links simbólicos) e você acabará chamando shutil.rmtree()um link simbólico, o que aumentará OSError("Cannot call rmtree on a symbolic link").
Rockallite 19/07/2014
1
@Rockallite fixo por cheque para IsLink
kevinf
1
Além disso: @kevinf está correto ao apontar a necessidade de uma islinkverificação aqui para manipular links simbólicos para diretórios corretamente. Eu adicionei essa verificação à resposta aceita.
Mark Amery
20

Este:

  • remove todos os links simbólicos
    • links mortos
    • links para diretórios
    • links para arquivos
  • remove subdiretórios
  • não remove o diretório pai

Código:

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

Como muitas outras respostas, isso não tenta ajustar as permissões para permitir a remoção de arquivos / diretórios.

Jon Chu
fonte
15

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

Uma solução mais robusta que contabilize arquivos e diretórios também seria (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)) )
fmonegaglia
fonte
1
para grandes operações, utilizando o gerador pode ser fraccionada mais eficientemap( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
user25064
realmente tentando usar isso, percebeu que o objeto do mapa deve ser iterado assim uma chamada à lista (ou algo que vai iterate) é necessária comolist(map(os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir))))
user25064
O primeiro incluído na resposta, o segundo não faz sentido para mim. Por que você deve iterar sobre uma função mapeada para uma iterável? O mapa faz isso.
Fmonegaglia 22/10/2015
1
No Python3, você precisa envolver map-se list para realmente iterar. Veja http://stackoverflow.com/questions/1303347/getting-a-map-to-return-a-list-in-python-3-x
paulwasit
Este definitivamente não funcionará se 'mydir' contém pelo menos uma pasta, como obras Desvincular para arquivos somente ...
kupsef
14

Observações: caso alguém rejeite minha resposta, tenho algo a explicar aqui.

  1. Todo mundo gosta de respostas curtas e simples. No entanto, às vezes a realidade não é tão simples.
  2. De volta à minha resposta. Eu sei que shutil.rmtree()poderia ser usado para excluir uma árvore de diretórios. Eu o usei muitas vezes em meus próprios projetos. Mas você deve perceber que o próprio diretório também será excluído porshutil.rmtree() . Embora isso possa ser aceitável para alguns, não é uma resposta válida para excluir o conteúdo de uma pasta (sem efeitos colaterais) .
  3. Vou mostrar um exemplo dos efeitos colaterais. Suponha que você tenha um diretório com proprietário personalizado e bits de modo, onde há muito conteúdo. Em seguida, você a exclui shutil.rmtree()e a reconstrói com os.mkdir(). E você obterá um diretório vazio com os bits padrão e herdados do proprietário e do modo. Embora você possa ter o privilégio de excluir o conteúdo e até o diretório, talvez não seja possível atrasar o proprietário original e os bits de modo no diretório (por exemplo, você não é um superusuário).
  4. Por fim, seja paciente e leia o código . É longo e feio (à vista), mas provou ser confiável e eficiente (em uso).

Aqui está uma solução longa e feia, mas confiável e eficiente.

Resolve alguns problemas que não são abordados pelos outros respondentes:

  • Ele lida corretamente com links simbólicos, incluindo a não chamada shutil.rmtree()de um link simbólico (que passará no os.path.isdir()teste se ele vincular a um diretório; até o resultado também os.walk()conterá diretórios simbólicos).
  • Ele lida bem com arquivos somente leitura.

Aqui está o código (a única função útil é 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")
Rockallite
fonte
Não entendo em que contexto alterar o modo de arquivo faz sentido. No meu Mac, os.remove, ao contrário da rmutilidade, tem o prazer de excluir somente leitura arquivos enquanto você possuí-los. Enquanto isso, se é um arquivo do qual você não possui apenas acesso somente leitura, não pode excluí-lo ou alterar suas permissões. Não conheço nenhuma situação em nenhum sistema em que você não os.removeconsiga excluir um arquivo somente leitura e ainda possa alterar suas permissões. Além disso, você usa lchmod, o que não existe no meu Mac, nem no Windows, de acordo com seus documentos. Para que plataforma esse código se destina ?!
Mark Amery
14

Estou surpreso que ninguém tenha mencionado o incrível pathlibpara fazer este trabalho.

Se você deseja apenas remover arquivos em um diretório, pode ser um oneliner

from pathlib import Path

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

Para também remover diretórios recursivamente, você pode escrever algo como isto:

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)
Husky
fonte
1
.iterdir()em vez de .glob(...)também deve funcionar.
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]

Um comentário anterior também menciona o uso de os.scandir no Python 3.5+. Por exemplo:

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)
Jacob Wan
fonte
1
os.path.isdir()não é uma maneira válida de distinguir entre um diretório regular e um link simbólico. Chamar shutil.rmtree()um link simbólico gerará uma OSErrorexceção.
Rockallite 19/07/2014
@Rockallite Thanks. Você está certo. Eu atualizei o exemplo.
Jacob Wan
8

Você pode estar melhor usando os.walk()isso.

os.listdir()não distingue arquivos de diretórios e você terá problemas para tentar desvinculá-los rapidamente. Há um bom exemplo de os.walk()como remover um diretório recursivamente aqui e dicas de como adaptá-lo às suas circunstâncias.

mhawke
fonte
6

Eu costumava resolver o problema desta maneira:

import shutil
import os

shutil.rmtree(dirpath)
os.mkdir(dirpath)
ProfHase85
fonte
7
Isso tem semântica radicalmente diferente do que a pergunta faz e não deve ser considerada uma resposta válida.
Fatuhoku 26/09
1
Com relação a isso, acho que "Excluir o conteúdo da pasta local" não envolve remover a própria pasta. O mesmo problema que esta resposta , exceto que recebemos muitas votações!
fatuhoku 26/09
3
É como responder à pergunta "Como faço para uma função retornar o número 1 no Python?" com def return_a_one (): launch_some_nukes () return 1
fatuhoku 26/09
2
É claro que a semântica é diferente: mas você também pode considerá-la como outra maneira de analisar o problema. Esta solução é perfeitamente válida, pois resolve o problema. Há uma diferença no exemplo do seu 'launch_some_nukes': 1. A solução é mais curta e fácil do que a aceita e, ao contrário da resposta citada, é válida. 2. o equivalente 'launch_some_nukes', neste caso, está excluindo e recriando uma pasta. A diferença entre a velha ea nova pasta é apenas o número inode (provavelmente irrelevante para a OP)
ProfHase85
2
É bastante demolição do arranha-céus e reconstruir um exatamente o mesmo tamanho;)
ProfHase85
5

Ainda outra solução:

import sh
sh.rm(sh.glob('/path/to/folder/*'))
Robin Winslow
fonte
1
Observe que isso shnão faz parte da biblioteca padrão e precisa ser instalado a partir do PyPI para que você possa usá-lo. Além disso, como isso realmente é chamado rmem um subprocesso, não funcionará no Windows onde rmnão existe. Isso também gerará uma exceção se a pasta contiver subdiretórios.
Mark Amery
5

Eu sei que é um tópico antigo, mas encontrei algo interessante no site oficial do python. Apenas para compartilhar outra ideia para remover todo o conteúdo de um diretório. Porque tenho alguns problemas de autorização ao usar shutil.rmtree () e não quero remover o diretório e recriá-lo. O endereço original é http://docs.python.org/2/library/os.html#os.walk . Espero que possa ajudar alguém.

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))
Sawyer
fonte
4

Para excluir todos os arquivos dentro do diretório, bem como seus subdiretórios, sem remover as próprias pastas, basta fazer o seguinte:

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))
Kevin Patel
fonte
3

Se você estiver usando um sistema * nix, por que não alavancar o comando system?

import os
path = 'folder/to/clean'
os.system('rm -rf %s/*' % path)
silverbullettt
fonte
3
Porque, como afirmado na pergunta, "O projeto atual é para Windows"
sox com Monica
3

Maneira bastante intuitiva de fazer isso:

import shutil, os


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


remove_folder_contents('/path/to/folder')
Manrique
fonte
3

Bem, acho que esse código está funcionando. Ele não excluirá a pasta e você pode usar esse código para excluir arquivos com a extensão específica.

import os
import glob

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

Eu tive que remover arquivos de 3 pastas separadas dentro de um diretório pai único:

directory
   folderA
      file1
   folderB
      file2
   folderC
      file3

Este código simples fez o truque para mim: (eu estou no 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)

Espero que isto ajude.

NicoBar
fonte
1

Resolvi o problema rmtree makedirsadicionando time.sleep()entre:

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

time.sleep(.5)

os.makedirs(folder_location, 0o777)
fislexico
fonte
0

Resposta para uma situação específica e limitada: supondo que você queira excluir os arquivos enquanto mantém a árvore de subpastas, você pode usar um algoritmo recursivo:

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)

Talvez um pouco fora de tópico, mas acho que muitos achariam útil

fmonegaglia
fonte
Usar os.walkda maneira mostrada em stackoverflow.com/a/54889532/1709587 talvez seja uma maneira melhor de excluir todos os arquivos enquanto mantém intacta a estrutura de diretórios.
Mark Amery
-1

Supondo temp_dirque seja excluído, um comando de linha única usando osseria:

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

Nota: Este é apenas um alinhador para excluir arquivos 'Não exclui diretórios.

Espero que isto ajude. Obrigado.

Fim-2-Fim
fonte
-1

Use o método abaixo para remover o conteúdo de um diretório, não o próprio diretório:

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)
Amir Rezazadeh
fonte
@FabioSpaghetti Negative
Amir Rezazadeh
obrigado Amir, estou à procura de uma solução que encontra uma determinada pasta em todos os subdiretórios de um diretório raiz e remove o conteúdo dessa pasta
FabioSpaghetti
Isso não adiciona nada de novo que ainda não foi mostrado na resposta aceita anos antes de você postar isso.
Mark Amery
-1

a maneira mais fácil de excluir todos os arquivos em uma pasta / remover todos os arquivos

import os
files = os.listdir(yourFilePath)
for f in files:
    os.remove(yourFilePath + f)
PyBoss
fonte
Falha se houver subdiretórios.
Mark Amery
-3

Isso deve resolver o problema, basta usar o módulo OS para listar e remover!

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

Trabalhou para mim, qualquer problema me avise!

B. Arquivador
fonte