空でないフォルダを削除/削除するにはどうすればよいですか?


847

空でないフォルダを削除しようとすると、「アクセスが拒否されました」エラーが発生します。私の試みで次のコマンドを使用しました:os.remove("/folder_name")

空でないフォルダ/ディレクトリを削除/削除する最も効果的な方法は何ですか?


32
また、ディレクトリが空であっても、正しい関数はos.rmdirであるため、os.removeは再び失敗します。
tzot 2008年

そして、特定のためにrm -rf行動を参照してください。stackoverflow.com/questions/814167/...
チロSantilli冠状病毒审查六四事件法轮功

回答:


1349
import shutil

shutil.rmtree('/folder_name')

標準ライブラリリファレンス:shutil.rmtree

設計上、rmtree読み取り専用ファイルを含むフォルダツリーで失敗します。読み取り専用ファイルが含まれているかどうかに関係なく、フォルダーを削除する場合は、次のコマンドを使用します。

shutil.rmtree('/folder_name', ignore_errors=True)

73
rmtree:読み取り専用ファイルがある場合に失敗しますstackoverflow.com/questions/2656322/...
シュリダールRatnakumar

9
これは私にとっては機能しません:トレースバック(最後の最後の呼び出し):ファイル "foo.py"、31行目<module>のshutil.rmtree(thistestdir)ファイル "/usr/lib/python2.6/shutil.py "、行225、rmtree onerror(os.rmdir、path、sys.exc_info())ファイル" /usr/lib/python2.6/shutil.py "、行223、rmtree os.rmdir(path)OSError: [Errno 90]ディレクトリが空ではありません: '/ path / to / rmtree'
Clayton Hughes

4
クレイトン:おそらく、rmtreeがデータの削除でビジーである間にファイルが同時に追加され、「rm -rf」は同じように失敗しました。
ddaa 2011

14
この機能がosパッケージに含まれていない理由を誰かが知っていますか?os.rmdirはまったく役に立たないようです。なぜこのように実装されているのかについての良い議論はありますか?
Malcolm

21
@MalcolmパッケージはOS関数のラッパーです。上のPOSIXのシステムでは、rmdirディレクトリが空でない場合には失敗しなければなりません。UbuntuWindowsは、この点でPOSIX準拠の一般的な例です。
Iain Samuel McLean Elder

138

以下からのpythonのドキュメントos.walk()

# Delete everything reachable from the directory named in 'top',
# assuming there are no symbolic links.
# CAUTION:  This is dangerous!  For example, if top == '/', it
# could delete all your disk files.
import os
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))

1
まあ、多分私はダウンモッドの間違いです。しかし、私はできる、今のところそれは正しいと思う。
ddaa 2008年

3
@ddaa:shutilを使用するのが間違いなく最も簡単な方法ですが、このソリューションについては間違いなく何の問題もありません。私はこの回答に賛成票を投じなかったでしょうが、今回はあなたの反対票をキャンセルするためだけに持っています:)
ジェレミー・カントレル

7
コード自体はpythonicです。実際のプログラムでshutil.rmtreeの代わりにこれを使用すると、Pythonのように動作しなくなります。つまり、「それを行う1つの明白な方法」を無視することになります。とにかく、これは意味論であり、downmodを削除します。
ddaa 2008年

2
@ddaa削除されたすべてのファイルまたはディレクトリをログに記録することはunpythonicですか?shutil.rmtreeでそれを行う方法がわかりませんか?
Jonathan Komar 2017年

4
@ddaaそれは思想、つまりレトリックのための食べ物でした。私は何をしているのか知っています。shutil.rmtreeが適切な「適合」できない理由を提供することで、「それを行う明白な方法」を再考したいと思うかもしれません。
Jonathan Komar 2017年

112
import shutil
shutil.rmtree(dest, ignore_errors=True)

1
これが正解です。私のシステムでは、特定のフォルダーのすべてを書き込み/読み取りに設定しているにもかかわらず、削除しようとするとエラーが発生します。ignore_errors=True問題を解決します。
Aventinus

3
私の答えでは、onerrorパラメータがの代わりに使用されていますignore_errors。このようにして、読み取り専用ファイルは無視されるのではなく削除されます。
Dave Chandler

はい、これはエラー時にファイルを削除しません。したがって、基本的にはrmtree()メソッド全体が無視されます。
Juha Untinen 2017

2
これは、6年前に受け入れられた回答を少し編集したもので、新しい回答ではなかったはずです。今からやります。
ジャン=フランソワ・コルベット

22

python 3.4から使用できます:

import pathlib

def delete_folder(pth) :
    for sub in pth.iterdir() :
        if sub.is_dir() :
            delete_folder(sub)
        else :
            sub.unlink()
    pth.rmdir() # if you just want to delete dir content, remove this line

どこpthpathlib.Pathインスタンスが。いいですが、最速ではないかもしれません。


10

docs.python.orgから:

この例は、一部のファイルに読み取り専用ビットが設定されているWindowsでディレクトリツリーを削除する方法を示しています。onerrorコールバックを使用して、読み取り専用ビットをクリアし、削除を再試行します。それ以降の障害はすべて伝播します。

import os, stat
import shutil

def remove_readonly(func, path, _):
    "Clear the readonly bit and reattempt the removal"
    os.chmod(path, stat.S_IWRITE)
    func(path)

shutil.rmtree(directory, onerror=remove_readonly)

7
import os
import stat
import shutil

def errorRemoveReadonly(func, path, exc):
    excvalue = exc[1]
    if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
        # change the file to be readable,writable,executable: 0777
        os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)  
        # retry
        func(path)
    else:
        # raiseenter code here

shutil.rmtree(path, ignore_errors=False, onerror=errorRemoveReadonly) 

ignore_errorsが設定されている場合、エラーは無視されます。それ以外の場合、onerrorが設定されていると、引数(func、path、exc_info)を使用してエラーを処理するために呼び出され、funcはos.listdir、os.remove、またはos.rmdirです。pathは、関数の失敗の原因となった関数への引数です。exc_infoは、sys.exc_info()によって返されるタプルです。ignore_errorsがfalseで、onerrorがNoneの場合、例外が発生します。ここにコードを入力してください


docsによると、onerrorによって発生した例外はキャッチされないので、ここでの発生のEnterコードは何を意味するのかわかりません
kmarsh 2015年

-1。これは、Dave Chandlerの回答に比べて複雑すぎるようです。また、読み取り専用を削除する場合は、ファイルを実行可能にする必要はありません。
idbrii

7

kkubasikの答えに基づいて、削除する前にフォルダが存在するかどうかを確認し、より堅牢

import shutil
def remove_folder(path):
    # check if folder exists
    if os.path.exists(path):
         # remove if exists
         shutil.rmtree(path)
    else:
         # throw your exception to handle this special scenario
         raise XXError("your exception") 
remove_folder("/folder_name")

6
これにより、可能性のある競合状態が発生します
Corey Goldberg

1
応じて最も神託ウェイ・ツー・削除-ファイル-どの-かもしれ-ない-EXIST、それはすることが望ましいですtry削除して、ハンドルexceptコールよりもexists()最初
TT--

6

dirツリー全体を削除し、dirの内容に関心がなくなったと確信している場合、dirツリー全体のクロールは愚かです... PythonからネイティブOSコマンドを呼び出してそれを実行します。より速く、効率的で、メモリ消費量が少なくなります。

RMDIR c:\blah /s /q 

または* nix

rm -rf /home/whatever 

Pythonでは、コードは次のようになります。

import sys
import os

mswindows = (sys.platform == "win32")

def getstatusoutput(cmd):
    """Return (status, output) of executing cmd in a shell."""
    if not mswindows:
        return commands.getstatusoutput(cmd)
    pipe = os.popen(cmd + ' 2>&1', 'r')
    text = pipe.read()
    sts = pipe.close()
    if sts is None: sts = 0
    if text[-1:] == '\n': text = text[:-1]
    return sts, text


def deleteDir(path):
    """deletes the path entirely"""
    if mswindows: 
        cmd = "RMDIR "+ path +" /s /q"
    else:
        cmd = "rm -rf "+path
    result = getstatusoutput(cmd)
    if(result[0]!=0):
        raise RuntimeError(result[1])

33
-1。使用する全体のポイントはshutil.rmdir、オペレーティングシステムの種類からユーザーを隔離することです。
mtrw 2010

3
概念は理解していますが、フォルダを完全に削除したいという事実をよく知っているとしたら、ファイルツリー全体をクロールする意味は何でしょうか。shutil.rmdirは、具体的にはos.listdir()、os.path.islink()などを呼び出します。必要なのはファイルシステムノードのリンクを解除することだけなので、必ずしも常に必要とは限らないいくつかのチェックです。MSAuto / WinCE開発用のMSWindowsなどの一部のビルドシステムでは、MSAutoバッチベースの開発が失敗した終了時にいくつかの奇妙なビルドファイルをロックするため、shtuil.rmdirはほとんど常に失敗し、rmdir / S / Qまたは再起動のみがクリーンアップに役立ちますそれら。
PM

2
うん、rmはカーネルにより近く、使用する時間、メモリ、CPUが少ない.....そして、私が言ったように、この方法を使用した理由は、MSAutoバッチビルドスクリプトによって残されたロックが原因でした...
PM

3
はい。ただし、shutilを使用すると、コードがクロスプラットフォームになり、プラットフォームの詳細が抽象化されます。
xshoppyx 2013

2
この回答は、読者が興味を持つ可能性のある特定の状況での回避策の非常に優れたリファレンスを提供するため、1未満には下がらないと思います。複数のメソッドを順番に並べて投稿することを楽しんでいます。したがって、これを使用する必要はありませんが、実行できることとその方法を知っています。
kmcguire 2014

5

上記の回答を完了するためのいくつかのpython 3.5オプション。(私はここでそれらを見つけるのが大好きだったでしょう)。

import os
import shutil
from send2trash import send2trash # (shutil delete permanently)

空の場合はフォルダを削除

root = r"C:\Users\Me\Desktop\test"   
for dir, subdirs, files in os.walk(root):   
    if subdirs == [] and files == []:
           send2trash(dir)
           print(dir, ": folder removed")

このファイルが含まれている場合は、フォルダも削除します

    elif subdirs == [] and len(files) == 1: # if contains no sub folder and only 1 file 
        if files[0]== "desktop.ini" or:  
            send2trash(dir)
            print(dir, ": folder removed")
        else:
            print(dir)

.srtまたは.txtファイルのみが含まれている場合はフォルダーを削除する

    elif subdirs == []: #if dir doesn’t contains subdirectory
        ext = (".srt", ".txt")
        contains_other_ext=0
        for file in files:
            if not file.endswith(ext):  
                contains_other_ext=True
        if contains_other_ext== 0:
                send2trash(dir)
                print(dir, ": dir deleted")

サイズが400kb未満の場合はフォルダを削除します。

def get_tree_size(path):
    """Return total size of files in given path and subdirs."""
    total = 0
    for entry in os.scandir(path):
        if entry.is_dir(follow_symlinks=False):
            total += get_tree_size(entry.path)
        else:
            total += entry.stat(follow_symlinks=False).st_size
    return total


for dir, subdirs, files in os.walk(root):   
    If get_tree_size(dir) < 400000:  # ≈ 400kb
        send2trash(dir)
    print(dir, "dir deleted")

4
インデントとコードを修正してくださいif files[0]== "desktop.ini" or:
Mr_and_Mrs_D

5

「純粋なpathlib」アプローチを追加したいと思います。

from pathlib import Path
from typing import Union

def del_dir(target: Union[Path, str], only_if_empty: bool = False):
    target = Path(target).expanduser()
    assert target.is_dir()
    for p in sorted(target.glob('**/*'), reverse=True):
        if not p.exists():
            continue
        p.chmod(0o666)
        if p.is_dir():
            p.rmdir()
        else:
            if only_if_empty:
                raise RuntimeError(f'{p.parent} is not empty!')
            p.unlink()
    target.rmdir()

これPathは順序付け可能であるという事実に依存しており、長いパスは、のように常に短いパスの後に常にソートされますstr。したがって、ディレクトリはファイルの前に来ます。並べ替えをにすると、ファイルはそれぞれのコンテナの前に来るため、1つのパスで1つずつリンクを解除/ rmdirできます。

利点:

  • それは外部バイナリに依存していません:すべてがPythonの電池内蔵モジュールを使用しています(Python> = 3.6)
  • 高速でメモリ効率が良い:再帰スタックなし、サブプロセスを開始する必要なし
  • それはクロスプラットフォームです(少なくとも、それは pathlibはPython 3.6で約束されてことです。上記の操作はWindowsで実行しないと述べられていません)
  • 必要に応じて、非常に細かいロギングを行うことができます。たとえば、削除が発生するたびにログに記録します。

使用例も提供できますか。del_dir(Path())?ありがとう
lcapra

@lcapra最初の引数として削除するディレクトリを指定して呼び出すだけです。
pepoluan

3
def deleteDir(dirPath):
    deleteFiles = []
    deleteDirs = []
    for root, dirs, files in os.walk(dirPath):
        for f in files:
            deleteFiles.append(os.path.join(root, f))
        for d in dirs:
            deleteDirs.append(os.path.join(root, d))
    for f in deleteFiles:
        os.remove(f)
    for d in deleteDirs:
        os.rmdir(d)
    os.rmdir(dirPath)

盲目的にそれらを削除する前にファイルをquarenteenに置くスクリプトを作成するのに最適です。
ラクリベイロ

3

shutilモジュールを使用したくない場合は、モジュールを使用できosます。

from os import listdir, rmdir, remove
for i in listdir(directoryToRemove):
    os.remove(os.path.join(directoryToRemove, i))
rmdir(directoryToRemove) # Now the directory is empty of files

2
os.removeディレクトリを削除できないためOsErrordirectoryToRemoveサブディレクトリが含まれている場合はこれが発生します。
代名詞

#pronetoraceconditions
kapad

3

10年後、Python 3.7とLinuxを使用して、これを行うにはまだ異なる方法があります。

import subprocess
from pathlib import Path

#using pathlib.Path
path = Path('/path/to/your/dir')
subprocess.run(["rm", "-rf", str(path)])

#using strings
path = "/path/to/your/dir"
subprocess.run(["rm", "-rf", path])

基本的に$ rm -rf '/path/to/your/dirは、ターミナルを使用して同じタスクを実行しているかのように、Pythonのサブプロセスモジュールを使用してbashスクリプトを実行します。それは完全にPythonではありませんが、それを実現します。

このpathlib.Path例を含めたのは、私の経験では、変化する多くのパスを処理するときに非常に役立つためです。pathlib.Pathモジュールをインポートして最終結果を文字列に変換する追加の手順は、多くの場合、開発期間のコストを削減します。Path.rmdir()空ではないディレクトリを明示的に処理するargオプションが付いていると便利です。


rmtreeような隠しフォルダに関する問題に遭遇したため、このアプローチにも切り替えました.vscode。このフォルダはテキストファイルとして検出され、エラーにより、このファイルはbusy削除できなかったことがわかりました。
ダニエルアイゼンライヒ

2

存在しない可能性がある場合でも(Charles Chowの回答の競合状態を回避して)フォルダーを削除するが、他のことがうまくいかない場合でもエラーが発生する(許可の問題、ディスク読み取りエラー、ファイルがディレクトリではないなど)

Python 3.xの場合:

import shutil

def ignore_absent_file(func, path, exc_inf):
    except_instance = exc_inf[1]
    if isinstance(except_instance, FileNotFoundError):
        return
    raise except_instance

shutil.rmtree(dir_to_delete, onerror=ignore_absent_file)

Python 2.7コードはほとんど同じです。

import shutil
import errno

def ignore_absent_file(func, path, exc_inf):
    except_instance = exc_inf[1]
    if isinstance(except_instance, OSError) and \
        except_instance.errno == errno.ENOENT:
        return
    raise except_instance

shutil.rmtree(dir_to_delete, onerror=ignore_absent_file)

1

os.walkでは、3つの1行のPython呼び出しで構成されるソリューションを提案します。

python -c "import sys; import os; [os.chmod(os.path.join(rs,d), 0o777) for rs,ds,fs in os.walk(_path_) for d in ds]"
python -c "import sys; import os; [os.chmod(os.path.join(rs,f), 0o777) for rs,ds,fs in os.walk(_path_) for f in fs]"
python -c "import os; import shutil; shutil.rmtree(_path_, ignore_errors=False)"

最初のスクリプトchmodのすべてのサブディレクトリ、2番目のスクリプトchmodのすべてのファイル。次に、3番目のスクリプトは、何の障害もなくすべてを削除します。

私はJenkinsジョブの「シェルスクリプト」からこれをテストしました(新しいPythonスクリプトをSCMに保存したくなかったため、1行のソリューションを検索しました)。これは、LinuxおよびWindowsで動作しました。


ではpathlib、あなたは一つに最初の2つのステップを組み合わせることができます:[p.chmod(0o666) for p in pathlib.Path(_path_).glob("**/*")]
pepoluan

0

簡単にするためにos.systemコマンドを使用できます。

import os
os.system("rm -rf dirname")

明らかなように、実際にはシステムターミナルを呼び出してこのタスクを実行します。


19
これはUnpythonicであり、プラットフォームに依存しています。
Ami Tavory

0

WINDOWS OSでフォルダ(空でもありません)またはファイルを削除する非常に簡単な方法を見つけました。

os.system('powershell.exe  rmdir -r D:\workspace\Branches\*%s* -Force' %CANDIDATE_BRANCH)

0

Windowsの場合、ディレクトリが空ではなく、読み取り専用ファイルがあるか、次のようなエラーが発生する場合

  • Access is denied
  • The process cannot access the file because it is being used by another process

これを試して、 os.system('rmdir /S /Q "{}"'.format(directory))

rm -rfLinux / Mac の場合と同等です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.