web-dev-qa-db-ja.com

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

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

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

742
Amara
import shutil

shutil.rmtree('/folder_name')

標準ライブラリ参照:shutil.rmtree

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

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

から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))
124
kkubasik
import shutil
shutil.rmtree(dest, ignore_errors=True)
101
Siva Mandadi

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インスタンスです。いいですが、最速ではないかもしれません。

16
yota
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()によって返されるTupleです。 ignore_errorsがfalseでonerrorがNoneの場合、例外が発生します。ここにコードを入力してください

7
RongyanZheng

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])
5
P M

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)
5
Dave Chandler

上記の答えを完成させるためのいくつかの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")

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

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")
5
JinSnow

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")
4
Charles Chow

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
3
Byron Filer
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)
2
amazingthere

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

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

明らかに、それは実際にこのタスクを達成するためにシステム端末を呼び出します。

2
user5449023

「純粋な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と同様に、長いパスは常に短いパスの後に常にソートされるという事実に依存しています。したがって、ディレクトリはファイルの前に配置されます。 reverseソートの場合、ファイルはそれぞれのコンテナの前に来るので、単純にリンク解除/ rmdirすることができます1つのパスを持つもの。

利点:

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

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

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

私がpathlib.Pathの例を含めた理由は、私の経験では変化する多くのパスを扱うときに非常に便利だからです。 pathlib.Pathモジュールをインポートして最終結果を文字列に変換するという余分なステップは、開発時間のために私にとってしばしば低コストです。 Path.rmdir()に空でないディレクトリを明示的に処理するためのargオプションが付いていれば便利でしょう。

1
RodogInfinite

Os.walkで、私は3つのワンライナー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の仕事の中の "Shell Script"からテストしました(私は新しいPythonスクリプトをSCMに保存したくなかったので、一行の解決策を探しました)そしてLinuxとWindowsでうまくいきました。

1

フォルダが存在しなくても( 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
Eponymous

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

Linux/Macのrm -rfと同等です。

0
Kartik Raj

私は フォルダ(空でなくても) または WINDOWS OS上のファイルを削除する非常に簡単な方法を見つけました

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