Bagaimana cara menghapus isi folder?

470

Bagaimana saya bisa menghapus konten folder lokal dengan Python?

Proyek saat ini adalah untuk Windows, tetapi saya juga ingin melihat * nix.

UnkwnTech
sumber
2
untuk * nix jujur ​​saya hanya akan menggunakanos.system('rm -rf folder')
Tilak Maddy

Jawaban:

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
sumber
4
Jika Anda bekerja dengan direktori yang sangat besar, dan khususnya direktori jaringan di windows, dan Anda dapat mengontrol lingkungan tempat program ini berjalan, mungkin ada baiknya menggunakan fungsi "os.scandir (folder)" Py3.5 alih-alih listdir. Sintaksnya sangat berbeda setelah itu, tetapi cukup sederhana untuk diterapkan; senang mempostingnya jika orang lain mau.
Michael Scott Cuthbert
Saya mendapat peringatan pylint dengan tulisan except Exception as e:itu W0703: Catching too general exception Exception. Apakah ada Pengecualian yang lebih spesifik untuk ditangkap atau haruskah saya abaikan?
John Hany
7
@ JohnHany, saya yakin Anda ingin menangkap OSError.
MikeB
246

Anda cukup melakukan ini:

import os
import glob

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

Anda tentu saja dapat menggunakan filter lain di jalur Anda, misalnya: /YOU/PATH/*.txt untuk menghapus semua file teks dalam direktori.

Blueicefield
sumber
12
@ Blueicefield *tidak akan mencantumkan file tersembunyi, kami juga harus menambahkanglob.glob('path/.*)
satoru
5
meskipun untuk menghapus daftar file, tampaknya lebih mudah bagi saya untuk melakukan:import sh; sh.rm(files)
Robin Winslow
2
Meskipun import sh; sh.rm(files)terlihat lebih cantik, Anda mengalami masalah jika ada lebih dari 1024 file dalam direktori.
Eugene
235

Anda dapat menghapus folder itu sendiri, serta semua isinya, menggunakan shutil.rmtree:

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


Hapus seluruh pohon direktori; path harus mengarah ke direktori (tetapi bukan tautan simbolis ke direktori). Jika ign_errors benar, kesalahan yang dihasilkan dari penghapusan yang gagal akan diabaikan; jika salah atau dihilangkan, kesalahan tersebut ditangani dengan memanggil pawang yang ditentukan oleh onerror atau, jika dihilangkan, mereka menimbulkan pengecualian.

Oli
sumber
270
Ini tidak hanya akan menghapus konten tetapi folder itu sendiri juga. Saya kira bukan itu pertanyaannya.
Iker Jimenez
3
Saya pikir itu jawaban yang bagus. Mengapa Anda tidak menghapus konten dan folder saja, lalu membuat ulang folder?
cssndrx
42
Karena direktori baru dan yang lama tidak akan sama. Jadi jika suatu program duduk di direktori, menunggu sesuatu, permadani akan ditarik keluar dari bawahnya.
Mike Cooper
30
Buat ulang direktori setelahnya rmtree. Sepertios.makedirs(dir)
Iulius Curt
3
@IuliusCurt tidak, saya memiliki direktori yang sudah terpasang di ram saya harus mengosongkan, dan sayangnya saya tidak bisa menghapus kemudian membuatnya kembali:OSError: [Errno 16] Device or resource busy
Arnaud P
80

Memperluas jawaban mhawke inilah yang telah saya terapkan. Ini menghapus semua konten folder tetapi tidak folder itu sendiri. Diuji di Linux dengan file, folder, dan tautan simbolis, harus bekerja pada Windows juga.

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
sumber
1
Mengapa 'berjalan' dan tidak hanya daftar konten folder?
Don
2
Ini adalah jawaban yang benar jika Anda ingin menghapus direktori juga. walkdigunakan untuk membagi dirs vs file, yang harus ditangani secara berbeda. Anda juga dapat menggunakan os.listdir, tetapi Anda harus memeriksa apakah setiap entri adalah direktori atau file secara manual.
dkamins
7
Ini dekat, tetapi os.walk dan shutil.rmtree keduanya bersifat rekursif. os.walk tidak diperlukan karena Anda hanya perlu file dan direktori di tingkat atas di dalam direktori untuk dibersihkan. Cukup gunakan pernyataan if pada elemen di os.listdir untuk melihat apakah masing-masing file atau direktori. Kemudian gunakan hapus / hapus tautan dan rmtree masing-masing.
Matthew Alpert
1
@MatthewAlpert Note, namun, itu os.walktidak akan muncul kembali di sini, karena mengembalikan generator satu-satunya yang secara rekursif melihat ke subdirektori ketika Anda mencoba untuk memajukannya, dan pada saat Anda telah melakukan iterasi pertama dari loop ini, tidak ada subdirektori kiri untuk melihat. Pada dasarnya, os.walkhanya digunakan di sini sebagai cara alternatif untuk membedakan folder tingkat atas dari file tingkat atas; rekursi tidak digunakan dan kami tidak membayar biaya kinerja untuk itu. Namun, ini eksentrik, dan saya setuju bahwa pendekatan yang Anda sarankan lebih baik hanya karena lebih eksplisit dan mudah dibaca.
Mark Amery
47

Menggunakan rmtreedan membuat ulang folder bisa berfungsi, tetapi saya mengalami kesalahan saat menghapus dan segera membuat kembali folder pada drive jaringan.

Solusi yang diusulkan menggunakan walk tidak berfungsi seperti yang digunakan rmtreeuntuk menghapus folder dan kemudian dapat mencoba untuk menggunakan os.unlinkfile yang sebelumnya ada di folder tersebut. Ini menyebabkan kesalahan.

globSolusi yang diposting juga akan mencoba untuk menghapus folder yang tidak kosong, menyebabkan kesalahan.

Saya sarankan Anda menggunakan:

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
sumber
1
Solusi Anda juga akan memunculkan kesalahan jika ada symlink ke direktori lain.
Blueicefield
@ Blueicefield - Bisakah Anda memberikan contoh. Saya telah menguji di linux menggunakan file dan folder yang disinkronkan, dan belum dapat menyebabkan kesalahan.
jgoeders
@jgoeders - Jika ada symlink ke direktori, os.path.isfile()akan kembali False(karena ia mengikuti symlinks), dan Anda akhirnya akan memanggil shutil.rmtree()symlink, yang akan muncul OSError("Cannot call rmtree on a symbolic link").
Rockallite
1
@Rockallite diperbaiki oleh cek ke islink
kevinf
1
@Kevinf juga benar untuk menunjukkan perlunya islinkpemeriksaan di sini untuk menangani symlink ke direktori dengan benar. Saya telah menambahkan tanda centang pada jawaban yang diterima.
Mark Amery
20

Ini:

  • menghapus semua tautan simbolik
    • tautan mati
    • tautan ke direktori
    • tautan ke file
  • menghapus subdirektori
  • tidak menghapus direktori induk

Kode:

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

Seperti banyak jawaban lain, ini tidak mencoba untuk menyesuaikan izin untuk memungkinkan penghapusan file / direktori.

Jon Chu
sumber
15

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

Solusi yang lebih kuat untuk file dan direktori juga adalah (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
sumber
1
untuk operasi besar menggunakan generator mungkin lebih efisienmap( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
user25064
sebenarnya mencoba untuk menggunakan ini, menyadari objek peta harus diulang sehingga panggilan ke daftar (atau sesuatu yang akan diulang) diperlukan sepertilist(map(os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir))))
user25064
Yang pertama termasuk dalam jawaban, yang kedua tidak masuk akal bagi saya. Mengapa Anda harus beralih pada fungsi yang dipetakan ke iterable? Peta melakukan itu.
fmonegaglia
1
Dalam Python3, Anda harus membungkus mapdi list untuk benar-benar iterate. Lihat http://stackoverflow.com/questions/1303347/getting-a-map-to-return-a-list-in-python-3-x
paulwasit
Yang ini pasti tidak akan berfungsi jika 'mydir' mengandung setidaknya satu folder, karena unlink hanya berfungsi untuk file ...
kupsef
14

Catatan: kalau-kalau ada orang yang memilih jawaban saya, saya punya sesuatu untuk dijelaskan di sini.

  1. Semua orang suka jawaban singkat dan sederhana. Namun, terkadang kenyataannya tidak sesederhana itu.
  2. Kembali ke jawabanku. Saya tahu shutil.rmtree()bisa digunakan untuk menghapus pohon direktori. Saya telah menggunakannya berkali-kali dalam proyek saya sendiri. Tetapi Anda harus menyadari bahwa direktori itu sendiri juga akan dihapus olehshutil.rmtree() . Meskipun ini mungkin dapat diterima untuk beberapa orang, itu bukan jawaban yang valid untuk menghapus isi folder (tanpa efek samping) .
  3. Saya akan menunjukkan contoh efek sampingnya. Misalkan Anda memiliki direktori dengan pemilik yang disesuaikan dan bit mode, di mana ada banyak konten. Kemudian Anda menghapusnya dengan shutil.rmtree()dan membangun kembali dengan os.mkdir(). Dan Anda akan mendapatkan direktori kosong dengan pemilik default (inherit) dan bit mode sebagai gantinya. Meskipun Anda mungkin memiliki hak istimewa untuk menghapus konten dan bahkan direktori, Anda mungkin tidak dapat mengatur kembali pemilik asli dan bit mode pada direktori (misalnya Anda bukan pengguna super).
  4. Akhirnya, bersabarlah dan baca kodenya . Panjang dan jelek (terlihat), tetapi terbukti andal dan efisien (digunakan).

Inilah solusi yang panjang dan jelek, tetapi dapat diandalkan dan efisien.

Ini menyelesaikan beberapa masalah yang tidak ditangani oleh penjawab lain:

  • Ini dengan benar menangani tautan simbolik, termasuk tidak memanggil shutil.rmtree()tautan simbolik (yang akan lulus os.path.isdir()tes jika tautannya ke direktori; bahkan hasil os.walk()berisi direktori yang terkait simbolik juga).
  • Ini menangani file read-only dengan baik.

Berikut kodenya (satu-satunya fungsi yang bermanfaat adalah 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
sumber
Saya tidak mengerti dalam konteks apa mengubah mode file masuk akal. Pada Mac saya, os.remove, tidak seperti yang rmutilitas, senang untuk menghapus read-only file selama Anda memiliki mereka. Sementara itu, jika itu adalah file yang bukan milik Anda yang hanya memiliki akses baca saja, maka Anda tidak dapat menghapusnya atau mengubah izinnya. Saya tidak tahu situasi apa pun di sistem mana pun di mana Anda tidak dapat menghapus file yang os.removehanya bisa dibaca dengan belum dapat mengubah izinnya. Selanjutnya, Anda menggunakan lchmod, yang tidak ada di Mac saya, atau di Windows sesuai dengan dokumennya. Untuk platform apa kode ini dibuat ?!
Mark Amery
14

Saya terkejut tidak ada yang menyebutkan yang luar biasa pathlibuntuk melakukan pekerjaan ini.

Jika Anda hanya ingin menghapus file dalam direktori, itu bisa menjadi oneliner

from pathlib import Path

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

Untuk juga menghapus direktori secara rekursif Anda dapat menulis sesuatu seperti ini:

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)
Serak
sumber
1
.iterdir()alih-alih .glob(...)juga harus bekerja.
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]

Komentar sebelumnya juga menyebutkan menggunakan os.scandir dalam Python 3.5+. Sebagai contoh:

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
sumber
1
os.path.isdir()bukan cara yang valid untuk membedakan antara direktori biasa dan tautan simbolik. Memanggil shutil.rmtree()tautan simbolis akan memunculkan OSErrorpengecualian.
Rockallite
@Rockallite Terima kasih. Kamu benar. Saya memperbarui contoh.
Jacob Wan
8

Anda mungkin lebih baik menggunakan os.walk()ini.

os.listdir()tidak membedakan file dari direktori dan Anda akan dengan cepat mendapat kesulitan mencoba memutuskan tautan ini. Ada contoh yang baik tentang penggunaan os.walk()untuk menghapus direktori secara rekursif di sini , dan memberi petunjuk tentang cara menyesuaikannya dengan keadaan Anda.

mhawke
sumber
6

Saya biasa memecahkan masalah dengan cara ini:

import shutil
import os

shutil.rmtree(dirpath)
os.mkdir(dirpath)
ProfHase85
sumber
7
Ini memiliki semantik yang sangat berbeda dari apa yang ditanyakan dan tidak seharusnya dianggap sebagai jawaban yang valid.
fatuhoku
1
Dengan hormat saya pikir "Hapus isi folder lokal" tidak melibatkan menghapus folder itu sendiri. Masalah yang sama dengan jawaban ini , kecuali satu mendapat banyak upvotes!
fatuhoku
3
Ini seperti menjawab pertanyaan, "Bagaimana saya memiliki fungsi mengembalikan angka 1 dengan Python?" dengan def return_a_one (): launch_some_nukes () return 1
fatuhoku
2
Tentu saja semantiknya berbeda: Tetapi Anda mungkin juga menganggapnya sebagai cara lain untuk melihat masalahnya. Solusi ini sangat valid karena memecahkan masalah. Ada perbedaan pada contoh 'launch_some_nukes' Anda: 1. Solusi lebih pendek dan lebih mudah daripada yang diterima dan berlawanan dengan jawaban yang Anda kutip valid. 2. setara dengan 'launch_some_nukes' dalam kasus ini adalah menghapus dan membuat ulang folder. Perbedaan antara folder lama dan baru hanyalah nomor inode (mungkin tidak relevan untuk OP)
ProfHase85
2
Ini agak menghancurkan gedung pencakar langit dan membangun kembali yang ukurannya persis sama;)
ProfHase85
5

Solusi Lain:

import sh
sh.rm(sh.glob('/path/to/folder/*'))
Robin Winslow
sumber
1
Perhatikan bahwa shitu bukan bagian dari pustaka standar dan perlu menginstal dari PyPI sebelum Anda dapat menggunakannya. Juga, karena ini benar-benar memanggil rmdalam suatu proses, itu tidak akan bekerja pada Windows di mana rmtidak ada. Ini juga akan memunculkan pengecualian jika folder tersebut berisi subdirektori.
Mark Amery
5

Saya tahu itu adalah utas lama tetapi saya telah menemukan sesuatu yang menarik dari situs resmi python. Hanya untuk berbagi ide lain untuk menghapus semua konten dalam direktori. Karena saya memiliki beberapa masalah otorisasi ketika menggunakan shutil.rmtree () dan saya tidak ingin menghapus direktori dan membuatnya kembali. Alamat asli adalah http://docs.python.org/2/library/os.html#os.walk . Semoga itu bisa membantu seseorang.

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))
Penggergaji
sumber
4

Untuk menghapus semua file di dalam direktori serta sub-direktori, tanpa menghapus foldernya sendiri, cukup lakukan ini:

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

Jika Anda menggunakan sistem * nix, mengapa tidak memanfaatkan perintah sistem?

import os
path = 'folder/to/clean'
os.system('rm -rf %s/*' % path)
silverbullettt
sumber
3
Karena, sebagaimana dinyatakan dalam pertanyaan, "Proyek saat ini adalah untuk Windows"
sox dengan Monica
3

Cara yang cukup intuitif untuk melakukannya:

import shutil, os


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


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

Yah, saya pikir kode ini berfungsi. Itu tidak akan menghapus folder dan Anda dapat menggunakan kode ini untuk menghapus file yang memiliki ekstensi tertentu.

import os
import glob

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

Saya harus menghapus file dari 3 folder terpisah di dalam direktori induk tunggal:

directory
   folderA
      file1
   folderB
      file2
   folderC
      file3

Kode sederhana ini membantu saya: (Saya menggunakan 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)

Semoga ini membantu.

NicoBar
sumber
1

Saya menyelesaikan masalah dengan rmtree makedirsmenambahkan time.sleep()antara:

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

time.sleep(.5)

os.makedirs(folder_location, 0o777)
physlexic
sumber
0

Jawaban untuk situasi terbatas dan spesifik: dengan asumsi Anda ingin menghapus file sambil mempertahankan pohon subfolder, Anda bisa menggunakan algoritma rekursif:

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)

Mungkin sedikit di luar topik, tapi saya pikir banyak yang akan merasa berguna

fmonegaglia
sumber
Menggunakan os.walkdengan cara yang ditunjukkan di stackoverflow.com/a/54889532/1709587 mungkin merupakan cara yang lebih baik untuk menghapus semua file sambil membiarkan struktur direktori tetap utuh.
Mark Amery
-1

Dengan asumsi temp_dirakan dihapus, perintah baris tunggal yang digunakan osadalah:

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

Catatan: Ini hanya 1-liner untuk menghapus file 'Tidak menghapus direktori.

Semoga ini membantu. Terima kasih.

End-2-End
sumber
-1

Gunakan metode di bawah ini untuk menghapus konten direktori, bukan direktori itu sendiri:

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
sumber
@FabioSpaghetti Negative
Amir Rezazadeh
terima kasih Amir, saya mencari solusi yang menemukan folder tertentu di semua subdirektori dari direktori root dan menghapus isi folder itu
FabioSpaghetti
Ini menambahkan tidak ada yang baru yang belum ditampilkan dalam jawaban yang diterima bertahun-tahun sebelum Anda memposting ini.
Mark Amery
-1

cara termudah untuk menghapus semua file dalam folder / hapus semua file

import os
files = os.listdir(yourFilePath)
for f in files:
    os.remove(yourFilePath + f)
PyBoss
sumber
Gagal jika ada subdirektori.
Mark Amery
-3

Ini seharusnya cukup dengan menggunakan modul OS untuk mendaftar dan kemudian hapus!

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

Bekerja untuk saya, masalah beri tahu saya!

B. Filer
sumber