Pythonでファイル・ディレクトリを削除するos.remove, shutil.rmtreeなど
Pythonでファイルを削除するにはos.remove()
、ディレクトリ(フォルダ)を中のファイルやサブディレクトリごとすべて削除するにはshutil.rmtree()
を使う。空のディレクトリのみを削除対象とするos.rmdir()
, os.removedirs()
もある。
いずれの場合もゴミ箱に入れられることなく削除されるので注意。
削除ではなく別のディレクトリに移動したりコピーしたりするにはshutil.move()
やshutil.copy()
を使う。
パスをオブジェクトとして操作するpathlibモジュールを使ってファイルやディレクトリを削除することもできる。条件を満たすファイルの一覧を取得して削除するような処理はpathlibを使ったほうが書きやすい。
本記事のサンプルコードでは以下のようにosモジュールとshutilモジュールをインポートしている。どちらも標準ライブラリに含まれているので追加のインストールは不要。
import os
import shutil
ファイルを削除: os.remove()
ファイルを削除するのはos.remove()
。
引数にファイルのパス(パス文字列やpathlib.Path
などのpath-like object)を指定すると削除される。
os.remove('temp/file.txt')
os.remove()
で削除できるのはファイルのみ。ディレクトリ(フォルダ)のパスを指定するとエラーになる。
# os.remove('temp/')
# PermissionError: [Errno 1] Operation not permitted: 'temp/'
ディレクトリを削除したい場合は以下で説明するshutil.rmtree()
やos.rmdir()
, os.removedirs()
などを使う。
ディレクトリを中身ごと削除: shutil.rmtree()
ディレクトリを中のファイルやサブディレクトリごと削除するにはshutil.rmtree()
を使う。
空のディレクトリのみを削除したい場合はos.rmdir()
, os.removedirs()
(後述)。
shutil.rmtree()
の引数として指定できるのはディレクトリを示すパスのみ。ファイルだとエラー。
# shutil.rmtree('temp/dir/file.txt')
# NotADirectoryError: [Errno 20] Not a directory: 'temp/dir/file.txt'
ディレクトリのパスを指定すると中のファイルやサブディレクトリごとまとめて削除される。ディレクトリ指定時の末尾の区切り文字(/
)はあってもなくてもよい。
shutil.rmtree('temp/dir/')
サブディレクトリ内にさらにファイルやディレクトリが存在する場合も再帰的にすべて削除される。
ディレクトリを空にする
ディレクトリを空にする場合は shutil.rmtree()
で全部削除してから新しく同名のディレクトリをos.mkdir()
で作成するのが簡単。
target_dir = 'temp'
shutil.rmtree(target_dir)
os.mkdir(target_dir)
ディレクトリ内の複数のファイルを条件に応じて一括で削除する方法は後述。
空のディレクトリを削除: os.rmdir(), os.removedirs()
空のディレクトリのみを削除対象とするos.rmdir()
, os.removedirs()
もある。
os.rmdir()
os.rmdir()
は空のディレクトリ一つが対象。
os.rmdir('temp/dir_empty/')
ディレクトリが空でない(ファイルやサブディレクトリを含んでいる)場合はエラーとなる。
# os.rmdir('temp/dir_not_empty/')
# OSError: [Errno 66] Directory not empty: 'temp/dir_not_empty/'
エラーで終了させずにディレクトリが空のときのみ削除するには例外処理を行う。以下の例ではディレクトリが空ではない場合はpass
で何の処理も行わずにスルーさせている。
try:
os.rmdir('temp/dir_not_empty/')
except OSError as e:
pass
中身をまとめて削除する場合は上述のshutil.rmtree()
を使う。
shutil.rmtree('temp/dir_not_empty/')
os.removedirs()
os.removedirs()
は空のディレクトリを末端から再帰的に削除する。
引数に末端の空ディレクトリを指定すると、親ディレクトリが空である場合に順番に削除される。
例えば、
os.removedirs('foo/bar/baz')
では最初にディレクトリ'foo/bar/baz'
を削除し、次に'foo/bar'
さらに'foo'
をそれらが空ならば削除します。末端のディレクトリが削除できなかった場合にはOSError
が送出されます。
os.removedirs() --- 雑多なオペレーティングシステムインタフェース — Python 3.11.4 ドキュメント
以下のファイル・ディレクトリ構成を例とする。
temp/
└── dir1/
├── dir2/
│ └── dir3/
└── file.txt
末端の空ディレクトリを指定する。
os.removedirs('temp/dir1/dir2/dir3')
結果は以下のようになる。指定したdir3
は空なので削除され、dir3
削除後のdir2
も空なので削除される。dir1
は空でないので削除されない。
temp/
└── dir1/
└── file.txt
複数のファイルを一括で削除
os.remove()
を使った実践的な例として、条件に応じて複数のファイルを一括で削除する方法を説明する。
なお、ファイル・ディレクトリ数が多い場合にglob.glob()
で**
を使うと時間がかかる可能性があるので、他の特殊文字で条件を絞れるのであればそちらを使ったほうがいい。
ワイルドカードで条件指定
globモジュールを使うとワイルドカード*
などの特殊文字を使ってファイルやディレクトリの一覧をリストで取得できる。詳しい使い方は以下の記事を参照。
以下のファイル・ディレクトリ構成を例とする。
temp/
├── 123.jpg
├── 456.txt
├── abc.txt
└── dir/
├── 000.csv
├── 789.txt
└── xyz.jpg
サブディレクトリ内も含めて、拡張子がtxt
のファイルを抽出して削除する。
import os
import glob
for p in glob.glob('temp/**/*.txt', recursive=True):
if os.path.isfile(p):
os.remove(p)
結果は以下の通り。
temp/
├── 123.jpg
└── dir/
├── 000.csv
└── xyz.jpg
上の例では問題ないが、条件によってはディレクトリが抽出される可能性もあるのでos.path.isfile()
を使ってファイルのみを対象としている。
ディレクトリを削除したい場合はos.path.isfile()
とos.remove()
のかわりにos.path.isdir()
とshutil.rmtree()
を使えばよい。
正規表現で条件指定
正規表現で条件を指定したい場合はreモジュールを使う。glob
だけでは実現できない複雑な条件を指定できる。
以下のファイル・ディレクトリ構成を例とする。
temp/
├── 123.jpg
├── 456.txt
├── abc.txt
└── dir/
├── 000.csv
├── 789.txt
└── xyz.jpg
glob.glob()
で**
と引数recursive=True
を使ってすべてのファイル・ディレクトリを再帰的にリストアップして、re.search()
などで正規表現による判定を行う。
サブディレクトリ内も含めて、ファイル名が数字のみで拡張子がtxt
またはcsv
のファイルを抽出して削除する。\d
は数字、+
は1回以上の繰り返し、(a|b)
はa
かb
のいずれかにマッチする。
import os
import glob
import re
for p in glob.glob('temp/**', recursive=True):
if os.path.isfile(p) and re.search('\d+\.(txt|csv)', p):
os.remove(p)
結果は以下の通り。
temp/
├── 123.jpg
├── abc.txt
└── dir/
└── xyz.jpg