Bir klasörün içeriği nasıl silinir?


470

Python'da yerel bir klasörün içeriğini nasıl silebilirim?

Mevcut proje Windows için, ama ben de * nix görmek istiyorum.


2
* nix dürüst olmak gerekirse ben sadece kullanmak istiyorumos.system('rm -rf folder')
Tilak Maddy

Yanıtlar:


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
Çok büyük bir dizin ve özellikle pencerelerde bir ağ dizini ile çalışıyorsanız ve bu programın çalıştığı ortamı kontrol edebiliyorsanız, Py3.5'in yerine "os.scandir (klasör)" işlevini kullanmaya değer olabilir. listdir. Sözdizimi bundan sonra oldukça farklıdır, ancak uygulanması oldukça basittir; diğerleri isterse göndermek için mutlu.
Michael Scott Cuthbert

İle bir PyLint uyarısı alıyorum except Exception as e:okur W0703: Catching too general exception Exception. Yakalanması gereken daha özel bir İstisna var mı yoksa yoksaymalıyım?
John Hany

7
@JohnHany, OSError'u yakalamak istediğine inanıyorum.
MikeB

246

Bunu basitçe yapabilirsiniz:

import os
import glob

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

Elbette yolunuzdaki başka bir filtreyi kullanabilirsiniz, örneğin: /YOU/PATH/*.txt bir dizindeki tüm metin dosyalarını kaldırmak için.


12
@Blueicefield *gizli dosyaları listelemez, biz de eklemeliyizglob.glob('path/.*)
satoru

5
dosya listesini silmekle birlikte, benim için daha basit görünüyor:import sh; sh.rm(files)
Robin Winslow

2
Daha import sh; sh.rm(files)güzel görünmekle birlikte, dizinde 1024'ten fazla dosya varsa sorun yaşarsınız.
Eugene

235

Aşağıdakileri kullanarak klasörün kendisini ve tüm içeriğini silebilirsiniz shutil.rmtree:

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


Dizin ağacının tamamını silme; yol bir dizini işaret etmelidir (ancak bir dizine sembolik bir bağlantı olmamalıdır). Eğer ignore_errors doğrudur, başarısız kaldırma kaynaklanan hatalar göz ardı edilecektir; yanlış veya ihmal varsa, bu tür hatalar tarafından belirtilen bir işleyici çağrılarak işlenir onerror bu atlanırsa veya, eğer bir istisna yükseltmek.


270
Bu sadece içeriği değil, klasörün kendisini de silecektir. Sorunun sorduğunu sanmıyorum.
Iker Jimenez

3
Bence bu iyi bir cevap. Neden sadece içeriği ve klasörü silmiyor ve klasörü yeniden oluşturmuyorsunuz?
cssndrx

42
Çünkü yeni dizin ve eskisi aynı olmayacak. Yani eğer bir program dizinde oturuyorsa, bir şeyler bekliyorsa, halının altından çekilmesini sağlayacaktır.
Mike Cooper

30
Sonra dizini yeniden oluşturun rmtree. Beğenos.makedirs(dir)
Iulius Curt

3
@IuliusCurt hayır, ben ram monte boş bir dizin var Boşaltmak gerekir, ve ne yazık ki ben sadece silmek ve sonra yeniden oluşturmak olamaz:OSError: [Errno 16] Device or resource busy
Arnaud P

80

Mhawke'nin cevabını genişleterek uyguladığım şey bu. Bir klasörün tüm içeriğini kaldırır, ancak klasörün kendisini kaldırmaz. Linux'ta dosya, klasör ve sembolik bağlantılarla test edilmiş, Windows üzerinde de çalışmalıdır.

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
Neden klasör içeriğini listelemekle kalmıyoruz?
Don

2
Dizinleri de silmek istiyorsanız bu doğru yanıttır. walkfarklı işlemesi gereken dosyaları ve dosyaları bölmek için kullanılır. Ayrıca kullanabilirsiniz os.listdir, ancak her girişin manuel olarak bir dizin veya dosya olup olmadığını kontrol etmeniz gerekir.
dkamins

7
Bu yakın, ama os.walk ve shutil.rmtree özyinelemeli. os.walk gereksizdir çünkü sadece dizinin içindeki en üst düzeydeki dosyalara ve dizinlere temizlenmesi gerekir. Her birinin bir dosya veya dizin olup olmadığını görmek için os.listdir öğesindeki öğeler üzerinde bir if ifadesi kullanmanız yeterlidir. Ardından sırasıyla remove / unlink ve rmtree kullanın.
Matthew Alpert

1
@MatthewAlpert Ancak, os.walkburada tekrarlamayacak çünkü bir jeneratör döndürür, çünkü ilerletmeye çalıştığınızda alt dizinlere yalnızca yinelemeli olarak bakar ve bu döngüyü ilk yinelemenizi yaptığınızda, alt dizinler yoktur. bakmak için ayrıldı. Özünde, os.walkburada üst düzey klasörleri üst düzey dosyalardan ayırmanın alternatif bir yolu olarak kullanılmaktadır; özyineleme kullanılmıyor ve bunun için hiçbir performans maliyeti ödemiyoruz. Yine de eksantriktir ve önerdiğiniz yaklaşımın daha açık ve okunaklı olduğu için daha iyi olduğunu kabul ediyorum.
Mark Amery

47

rmtreeKlasörü kullanmak ve yeniden oluşturmak işe yarayabilir, ancak ağ sürücülerindeki klasörleri siler ve hemen yeniden oluştururken hatalarla karşılaştım.

Walk kullanarak önerilen çözüm, rmtreeklasörleri kaldırmak için kullandığı için çalışmaz ve daha sonra os.unlinkbu klasörlerde bulunan dosyalarda kullanmaya çalışabilir . Bu bir hataya neden olur.

Gönderilen globçözüm, boş olmayan klasörleri silmeye ve hatalara neden olmaya çalışır.

Ben kullanmanızı öneririz:

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
Başka bir dizine bir sembolik bağ varsa, çözümünüz de bir hata oluşturur.
Blueicefield

@Blueicefield - Bir örnek verebilir misiniz? Linux'ta bir sembolik dosya ve klasör kullanarak test ettim ve henüz bir hataya neden olamadım.
jgoeders

@jgoeders - Bir dizine bir sembolik bağlantı varsa, os.path.isfile()geri döner False(sembolik bağlantıları takip ettiği için) ve sonunda shutil.rmtree()bir sembolik bağlantının çağrılmasını sağlarsınız OSError("Cannot call rmtree on a symbolic link").
Rockallite

1
@Rockallite check to islink tarafından düzeltildi
kevinf

1
Ayrıca: @kevinf, islinkdizinleri doğru şekilde yönlendirmek için burada bir kontrol yapılması gerektiğini belirtmek için doğrudur . Kabul edilen cevaba böyle bir çek ekledim.
Mark Amery

20

Bu:

  • tüm sembolik bağlantıları kaldırır
    • ölü bağlantılar
    • dizinlere bağlantılar
    • dosyalara bağlantılar
  • alt dizinleri kaldırır
  • üst dizini kaldırmaz

Kod:

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

Diğer birçok yanıtta, bu, dosyaların / dizinlerin kaldırılmasını sağlamak için izinleri ayarlamaya çalışmaz.


15

Bir oneliner olarak:

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

Dosyalar ve dizinler için de daha sağlam bir çözüm (2.7) olacaktır:

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
jeneratörü kullanan büyük işlemler için fraksiyonel olarak daha verimli olabilirmap( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
user25064

Aslında bunu kullanmaya çalışırken, harita nesnesinin yinelenmesi gerektiğini fark etti, böylece bir liste çağrısı (veya yinelenecek bir şey) gereklilist(map(os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir))))
user25064

Birincisi cevaba dahil, ikincisi benim için hiçbir anlam ifade etmiyor. Neden bir yinelenebilir ile eşlenen bir işlev üzerinde yineleme yapmalısınız? Harita bunu yapar.
fmonegaglia

1
Python3 olarak, sarmak zorunda mapiçinde list aslında yinelemenizi. Bkz. Http://stackoverflow.com/questions/1303347/getting-a-map-to-return-a-list-in-python-3-x
paulwasit

'Mydir' en azından bir klasör içeriyorsa, bu kesinlikle çalışmaz, çünkü unlink sadece dosyalar için çalışır ...
kupsef

14

Notlar: Birisinin cevabımı oylamaması durumunda, burada açıklayacağım bir şey var.

  1. Herkes kısa 'n' basit cevapları sever. Ancak, bazen gerçek o kadar basit değildir.
  2. Cevabıma geri dön. shutil.rmtree()Bir dizin ağacını silmek için kullanılabileceğini biliyorum . Kendi projelerimde birçok kez kullandım. Ancak dizinin kendisinin de tarafından silineceğinishutil.rmtree() anlamalısınız . Bu bazıları için kabul edilebilir olsa da , bir klasörün içeriğini silmek için geçerli bir cevap değildir (yan etkileri olmadan) .
  3. Size yan etkilere bir örnek göstereceğim. Varsayalım ki bir dizininiz varÇok sayıda içeriğin bulunduğu özelleştirilmiş sahip ve mod bitlerine . Sonra ile silin shutil.rmtree()ve ile yeniden oluşturun os.mkdir(). Bunun yerine varsayılan (devralınmış) sahip ve mod bitleriyle boş bir dizin elde edersiniz . İçeriği ve hatta dizini silme ayrıcalığınız olsa da, dizindeki orijinal sahibi ve mod bitlerini geri ayarlayamayabilirsiniz (örn. Süper kullanıcı değilsiniz).
  4. En sonunda, sabırlı olun ve kodu okuyun . Uzun ve çirkin (görünürde), ancak güvenilir ve verimli (kullanımda) olduğu kanıtlanmıştır.

İşte uzun ve çirkin ama güvenilir ve verimli bir çözüm.

Diğer yanıtlayıcılar tarafından ele alınmayan birkaç sorunu çözer:

  • Sembolik bir bağlantıyı çağırmamak da dahil olmak üzere shutil.rmtree()(os.path.isdir() bir dizine os.walk()bağlanırsa testi ; hatta sembolik bağlantılı dizinler de içerir).
  • Salt okunur dosyaları güzelce işler.

İşte kod (tek kullanışlı fonksiyon 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")

Dosya modunu değiştirmenin hangi bağlamda mantıklı olduğunu anlamıyorum. Benim Mac'te, os.remove, aksinerm fayda, bunları kendi sürece salt okunur olarak dosyaları silmek için mutludur. Eğer bir dosya varsa arada, yok yalnızca salt okunur erişimi olduğunu kendi, o zaman silemezsiniz ya da izinleri değiştirin. Herhangi bir sistemde salt okunur bir dosyayı silemeyeceğiniz os.removeancak izinlerini değiştiremeyeceğiniz bir durum bilmiyorum . Ayrıca, lchmodMac bilgisayarımda veya Windows'ta dokümanlarına göre mevcut olmayanları kullanırsınız . Bu kod hangi platform için tasarlanmıştır ?!
Mark Amery

14

Kimsenin pathlibbu işi yapmak için harikalardan bahsetmediğine şaşırdım .

Yalnızca bir dizindeki dosyaları kaldırmak istiyorsanız, bir oneliner olabilir

from pathlib import Path

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

Ayrıca dizinleri özyinelemeli olarak kaldırmak için şöyle bir şey yazabilirsiniz:

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()yerine .glob(...)çalışmalı.
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]

Daha önceki bir yorumda Python 3.5+ sürümünde os.scandir kullanıldığından bahsediliyor. Örneğin:

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()normal bir dizin ile sembolik bir bağlantı arasında ayrım yapmak için geçerli bir yol değildir. shutil.rmtree()Sembolik bir bağlantıyı çağırmak OSErroristisnayı artıracaktır .
Rockallite

@Rockallite Teşekkürler. Haklısın. Örneği güncelledim.
Jacob Wan

8

Bunun os.walk()için kullanmak daha iyi olabilir .

os.listdir()dosyaları dizinlerden ayırmaz ve hızlı bir şekilde bunların bağlantısını kaldırmaya çalışırken sorun yaşarsınız. Orada kullanmanın iyi bir örnektir os.walk()yinelemeli bir dizin kaldırmak için buraya senin koşullarına adapte nasıl ipuçları ve.


6

Problemi şu şekilde çözerdim:

import shutil
import os

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

7
Bu, sorunun sorduğundan çok farklı bir anlambilime sahiptir ve geçerli bir cevap olarak görülmemelidir.
fatuhoku

1
Saygı ile "Yerel klasörün içeriğini sil" klasörünün kaldırılmasını gerektirmediğini düşünüyorum. Bu cevapla aynı sorun , ancak bir sürü upvotes var!
fatuhoku

3
"Python'da 1 numarayı nasıl döndüren bir fonksiyonum var?" def ile return_a_one (): launch_some_nukes () 1 dönüş
fatuhoku

2
Elbette anlambilim farklıdır: Ama bunu soruna bakmak için başka bir yol olarak da düşünebilirsiniz. Bu çözüm, sorunu çözdüğü için tamamen geçerlidir. 'Launch_some_nukes' örneğinizde bir fark var: 1. Çözüm, kabul edilenden daha kısa ve daha kolay ve alıntıladığınız cevaba karşılık geçerli. 2. Bu durumda 'launch_some_nukes' eşdeğeri bir klasörü siliyor ve yeniden oluşturuyor. Eski ve yeni klasör arasındaki fark sadece inode numarasıdır (muhtemelen OP için önemsizdir)
ProfHase85 31:13

2
Oldukça gökdeleni yıkıyor ve tamamen aynı boyutta bir tane inşa ediyor;)
ProfHase85

5

Yine Başka Bir Çözüm:

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

1
Not shstandart kütüphanenin parçası değildir ve bunu kullanmadan önce PyPI gelen yükleme ihtiyacı var. Ayrıca, bu aslında rmbir alt işlem gerektirdiğinden, var olmayan Windows üzerinde rmçalışmaz. Klasör herhangi bir alt dizin içeriyorsa da bir istisna oluşturur.
Mark Amery

5

Ben eski bir iplik konw ama python resmi sitesinden ilginç bir şey buldum. Bir dizindeki tüm içeriği kaldırmak için başka bir fikri paylaşmak içindir. Çünkü shutil.rmtree () kullanırken bazı yetkilendirme sorunlarım var ve dizini kaldırmak ve yeniden oluşturmak istemiyorum. Orijinal adres http://docs.python.org/2/library/os.html#os.walk şeklindedir . Umarım bu birine yardımcı olabilir.

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

Klasörlerin kendisini kaldırmadan dizindeki tüm dosyaları ve alt dizinlerini silmek için şunları yapın:

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

* Nix sistemi kullanıyorsanız neden sistem komutundan yararlanmıyorsunuz?

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

3
Çünkü, "Mevcut proje Windows için" sorusunda belirtildiği gibi
Monica ile

3

Bunu yapmanın oldukça sezgisel yolu:

import shutil, os


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


remove_folder_contents('/path/to/folder')

3

Bence bu kod çalışıyor. Klasörü silmez ve belirli bir uzantıya sahip dosyaları silmek için bu kodu kullanabilirsiniz.

import os
import glob

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

3

Tek bir üst dizin içindeki 3 ayrı klasördeki dosyaları kaldırmak zorunda kaldım:

directory
   folderA
      file1
   folderB
      file2
   folderC
      file3

Bu basit kod benim için hile yaptı: (Ben Unix'teyim)

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)

Bu yardımcı olur umarım.


1

Aşağıdakileri rmtree makedirsekleyerek sorunu çözdüm time.sleep():

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

time.sleep(.5)

os.makedirs(folder_location, 0o777)

0

Sınırlı, özel bir durum için yanıt verin: alt klasörler ağacını korurken dosyaları silmek istediğinizi varsayarak, yinelemeli bir algoritma kullanabilirsiniz:

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)

Belki biraz konu dışı, ama bence birçoğu yararlı bulacaktır


Stackoverflow.com/a/54889532/1709587os.walk adresinde gösterilen şekilde kullanmak , dizin yapısını olduğu gibi bırakarak tüm dosyaları silmenin daha iyi bir yoludur.
Mark Amery

-1

temp_dirSilineceği varsayılarak , tek bir satır komutu kullanılarak os:

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

Not: Bu yalnızca dosyaları silmek için 1 astarlıdır 'Dizinleri silmez.

Bu yardımcı olur umarım. Teşekkürler.


-1

Dizinin kendisini değil, bir dizinin içeriğini kaldırmak için aşağıdaki yöntemi kullanın:

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 Negatif
Amir Rezazadeh

teşekkür ederim Amir, bir kök dizinin tüm alt dizinlerinde belirli bir klasörü bulur ve bu klasörün içeriğini kaldırır bir çözüm
arıyorum

Bu, siz göndermeden yıllar önce kabul edilen yanıtta gösterilmeyen yeni bir şey eklemez.
Mark Amery

-1

bir klasördeki tüm dosyaları silmenin / tüm dosyaları silmenin en kolay yolu

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

Alt dizinler varsa başarısız olur.
Mark Amery

-3

Bu sadece liste ve sonra kaldırmak için OS modülünü kullanarak hile yapmak gerekir!

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

Benim için çalıştı, herhangi bir sorun bana bildirin!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.