osモジュールのmkdir/rmdir/makedirs/removedirs関数とshutilモジュールのrmtree関数を使って、ディレクトリを作成/削除する方法を紹介。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
import os
# os.mkdir関数を使ったディレクトリ作成
target_dir = 'sample_dir'
os.mkdir(target_dir)
os.mkdir(target_dir) # FileExistsError
# os.rmdir関数を使ったディレクトリ削除
target_dir = 'sample_dir'
os.rmdir(target_dir)
# os.makedirs関数を使った再帰的なディレクトリ作成
target_dir = 'sample_dir/dir2/dir3'
os.makedirs(target_dir)
# os.rmdir関数は空でないディレクトリは削除できない
target_dir = 'sample_dir/dir2'
os.rmdir(target_dir) # OSError:dir2ディレクトリにはdir3ディレクトリがある
# os.removedirs関数を使った再帰的なディレクトリ削除
os.removedirs(target_dir) # 最下層のディレクトリから順に削除していく
# os.removedirs関数は途中に空でないディレクトリがあるとそこで削除を終了する
target_dir = 'sample_dir/dir2/dir3'
os.makedirs(target_dir)
os.mkdir('sample_dir/dir2/foo')
os.removedirs(target_dir) # dir3を削除した後、dir2が空ではないので削除できない
# 指定したディレクトリの内容を全て削除する
import shutil
shutil.rmtree('sample_dir')
Pythonのコードからファイルシステム上でディレクトリを作成したり削除したりするには幾つかの方法がある。
本稿ではこのうちosモジュールを使用する方法とshutilモジュールのrmtree関数を使ってディレクトリを再帰的に削除する方法を紹介する。
ディレクトリを作成/削除するには、osモジュールが提供する以下の関数を使う。
まずはos.mkdir関数を使ってディレクトリを作成し、os.rmdir関数を使ってそのディレクトリを削除してみよう。
os.mkdir関数の一番簡単な使い方は作成したいディレクトリの名前を引数に指定することだ。以下に例を示す。
import os
target_dir = 'sample_dir'
os.mkdir(target_dir)
os.mkdir(target_dir) # FileExistsError
この例はカレントディレクトリにsample_dirという名前のディレクトリを作成するものだ。os.mkdir関数は既に存在するディレクトリを作成しようとすると、FileExistsError例外となる点には注意しよう。例外を回避するのであれば、以下のようにos.pathモジュールのexists関数を使用して、ディレクトリがないことを確認する。
if not os.path.exists(target_dir):
os.mkdir(target_dir)
else:
print(f'{target_dir} already exists')
あるいは、pathlibモジュールのPathクラスのインスタンスが持つmkdirメソッドにはexist_okパラメーターがあり、これにTrueを指定すると既存のディレクトリを作成しようとしたときに例外が発生しないようになる(pathlibモジュールを使ったディレクトリの作成/削除については別稿で紹介する)。
上で作成したsample_dirディレクトリを削除するには、os.rmdir関数にそのディレクトリを指定するだけだ。以下に例を示す。
target_dir = 'sample_dir'
os.rmdir(target_dir)
存在しないディレクトリを削除しようとしたときには、FileNotFoundError例外が発生する。また、削除対象のディレクトリは空である必要がある。つまり、ファイルやディレクトリを含まないディレクトリしか削除できない(空でないディレクトリを削除しようとするとOSError例外が発生し、ディレクトリが空ではないというメッセージが伝えられる)。
os.mkdir関数で一度に作成できるのは指定したディレクトリ1つだ。存在しない複数階層のディレクトリを作成することはできない。例えば、カレントディレクトリの下にsample_dirディレクトリを、その下にdir2ディレクトリを、さらにその下にdir3ディレクトリを作成したいというときには、os.mkdir関数を3回呼び出す必要がある。
こうしたときには、os.makedirs関数を使用する。この関数は指定したディレクトリ(上の例なら「sample_dir/dir2/dir3」)を作成する上で必要なディレクトリを全て作成してくれる。以下に例を示す。
target_dir = 'sample_dir/dir2/dir3'
os.makedirs(target_dir)
このような複数階層のディレクトリをos.rmdir関数で削除するには、最下層のディレクトリから順番に削除していく必要がある(このときには上で述べたように、それぞれのディレクトリが空である必要もある)。
例えば、上の例ではsample_dir/dir2/dir3ディレクトリを作成しているが、ここで下のようなコードで、sample_dir/dir2ディレクトリを削除しようとすると、OSError例外が発生する。
target_dir = 'sample_dir/dir2'
os.rmdir(target_dir) # OSError
これはsample_dir/dir2ディレクトリの下にはdir3ディレクトリがある、つまり空ではないために削除できないからだ。複数階層のディレクトリをまとめて削除するには、次に紹介するos.removedirs関数を使用する。
os.removedirs関数は指定したディレクトリを再帰的に削除する。注意点は削除対象の最上位のディレクトリを指定するのではなく、削除したいディレクトリパス全体を指定する点だ。以下に例を示す。
target_dir = 'sample_dir/dir2/dir3'
os.removedirs(target_dir) # 最下層のディレクトリから順に削除していく
これは上で作成したsample_dir/dir2/dir3ディレクトリをまるごと削除するコードである。
なお、os.rmdir関数と同様、削除対象の個々のディレクトリは空である必要がある。上のコード例であれば、まずdir3ディレクトリが(空なら)削除され、次にdir2が(空なら)削除され、最後にdir1が(空なら)削除される。
途中のディレクトリが空でないときには、そこでディレクトリの削除処理が終了する。それよりも下層にあって削除されたディレクトリは削除されたままとなる。以下に例を示す。
target_dir = 'sample_dir/dir2/dir3'
os.makedirs(target_dir)
os.mkdir('sample_dir/dir2/foo')
os.removedirs(target_dir) # dir3を削除した後、dir2が空ではないので削除できない
この例ではsample_dir/dir2/dir3ディレクトリを作成した後、sample_dir/dir2ディレクトリの下にfooディレクトリを作成している。そして、sample_dir/dir2/dir3ディレクトリを再帰的に削除しようとしているが、dir3ディレクトリを削除しても、dir2ディレクトリにはまだfooディレクトリがある(空ではない)ので、そこでディレクトリ全体の削除処理が終了する(ただし、例外は発生しないので注意すること)。
このことは以下のコードで確認できる。
d_entries = [item for item in os.scandir('sample_dir')]
print(d_entries) # [<DirEntry 'dir2'>]
d_entries = [item for item in os.scandir('sample_dir/dir2')]
print(d_entries) # [<DirEntry 'foo'>]
最初の2行はsample_dirディレクトリの下にどんなファイル/ディレクトリがあるかを調べるものだ。結果を見ると、dir2ディレクトリが残っていることが分かる。
次の2行はdir2ディレクトリにどんなファイル/ディレクトリがあるかを調べるものだ。結果を見ると、dir3ディレクトリは削除されたが、fooディレクトリが残っていることが分かる。このために、os.removedirs関数は途中でディレクトリ削除処理を中断したということだ。
上のようにディレクトリ階層の中にさまざまなファイルやディレクトリが存在しているときには、os.removedirs関数は役には立たない。os.listdir関数やos.scandir関数を使って自分でディレクトリを走査しながら、ファイルやディレクトリを下層から上層に向けて削除していくコードを書いてもよいが、shutilモジュールのrmtree関数が使うのが簡単だろう。以下に使用例を示す。
import shutil
shutil.rmtree('sample_dir')
Copyright© Digital Advantage Corp. All Rights Reserved.