Pythonのプログラム内からディレクトリを作成したり、ファイルやディレクトリを削除したり、ディレクトリ階層を走査する方法を紹介する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
Pythonに標準で添付されているosモジュールは、カレントディレクトリ(現在の作業ディレクトリ/フォルダー。カレントワーキングディレクトリとも呼ぶ)を取得したり、カレントディレクトリを移動したりするための関数を提供している。今回は、それらについて見ていこう(なお、「os」という名前からも想像できるが、osモジュールにはファイルシステム操作以外の機能も含まれているが、それらについては今回は紹介しない)。
Pythonのプログラムやスクリプトを現在実行している、またはJupyter NotebookやPythonの対話環境で現在対話的にPythonのコードを実行している「カレントディレクトリ」(現在作業をしているディレクトリ/フォルダーのこと)を取得するにはosモジュールのgetcwd関数を使用する。なお、以下では「osモジュールのXXX関数」を単に「os.XXX関数」と表記する。os.getcwd関数の基本構文を以下に示す。
os.getcwd()
カレントディレクトリを表す文字列を取得する。
Windows環境とUNIX/Linux環境、macOS環境ではファイルシステムの違い、ディレクトリ階層を区切る文字の違い、プログラムや対話環境を起動したディレクトリなどに応じて、得られる文字列にはそれぞれに違いがある。例えば、単純な以下のコードでも得られる値は異なるものになる。
import os
print(os.getcwd())
これらは本連載で使用している「Try Jupyter」ページからたどれるJupyter Notebook、macOS、Windows上でローカルに起動したJupyter Notebook環境で、上記コードを実行した例を以下に示す。
一番下のWindows版の出力ではバックスラッシュ(円マーク)が表示されている。そのため、自分で文字列を使って、パスを操作するときには円マークの扱いに注意する必要があることは覚えておこう。ただし、現在ではWindowsでもディレクトリの区切り文字としてスラッシュ「/」を解釈してくれるので、本稿では区切り文字としてはスラッシュを使用していく。
PythonはOSごとのファイルシステムやその表現方法の違いをなるべく意識しないで済むような仕組みになっている。例えば、osモジュールおよびos.pathモジュールではファイルやディレクトリのパスを抽象化した操作を行ったり、ファイルの属性を調べたりするための関数やクラスが定義されている。また、実行画面については本連載で使用しているJupyter Notebook環境のものをメインで掲載していくことにする。
カレントディレクトリを移動するにはos.chdir関数を使用する。
os.chdir(path)
pathで表されるディレクトリをカレントディレクトリにする。
パラメーター | 説明 |
---|---|
path | カレントディレクトリにするディレクトリのパス |
os.chdir関数のパラメーター |
pathには絶対パス(特定のディレクトリを指定するのに、ファイルシステムのルートディレクトリあるいはドライブ文字とルートディレクトリからの完全なディレクトリ経路)あるいは相対パス(カレントディレクトリを基点としたディレクトリの経路)を指定できる(これらは以下で紹介する関数でも同様)。
カレントディレクトリを移動するコードの例を以下に示す。
os.chdir('..') # 相対パス
print(os.getcwd())
os.chdir('/home/jovyan/binder') # 絶対パス
print(os.getcwd())
このコードでは、まずカレントディレクトリの親ディレクトリ(親ディレクトリを意味する「..」のみを指定しているので、ここではこれはカレントディレクトリの親ディレクトリを意味する)に移動してから、そのカレントディレクトリを表示して、次に最初にいたディレクトリ(先ほどのos.getcwd関数で調べたディレクトリを絶対パスで指定している)にカレントディレクトリを戻している。本連載では「Try Jupyter」ページからたどれるJupyter Notebook環境を使用しているので、上のコードを他の環境で実行すると例外が発生するので注意しよう。
実行結果を以下に示す。
特定のディレクトリにどんなファイルやディレクトリが含まれているかを調べるには、os.listdir関数あるいはos.scandir関数を使用する(os.scandir関数はPython 3.5以降で利用可能)。
os.listdir(path='.')
os.scandir(path='.')
os.listdir関数はpathで表されるディレクトリに含まれるファイルやディレクトリの名前を要素とするリストを返す。pathを省略すると、カレントディレクトリに含まれるファイルやディレクトリの名前を含んだリストが返される。
os.scandir関数はpathで表されるディレクトリに含まれるファイルやディレクトリを表すos.DirEntryオブジェクトを列挙するのに使えるイテレータを返す。pathを省略すると、カレントディレクトリに含まれるファイルやディレクトリを表すos.DirEntryオブジェクトを列挙するのに使えるイテレータが返される。
パラメーター | 説明 |
---|---|
path | どんなファイルやリストがあるかを調べたいディレクトリのパス。省略時にはカレントディレクトリの内容が調べられる |
os.listdir関数/os.scandir関数のパラメーター |
以下にこれらの利用例を示す。
print('using os.listdir')
for name in os.listdir():
if os.path.isfile(name):
print(f'file: {name}')
else:
print(f'dir: {name}')
print('using os.scandir')
for entry in os.scandir():
if entry.is_file():
print(f'file: {entry.name}')
else:
print(f'dir: {entry.name}')
このコードは、カレントディレクトリに含まれるファイルやディレクトリの一覧を取得して、それらがファイルかどうかを調べて、ファイルであればその旨を、そうでなければ安直にディレクトリであると判断してその旨を表示している。
os.listdir関数はファイル/ディレクトリの名前を要素とするリストを戻り値とするので、それらがファイルかどうかをos.pathモジュールで公開されているisfile関数にその名前を渡して調べている。
一方のos.scandir関数では、そうした属性をディレクトリのスキャン時にあらかじめ取得して、ファイル名もしくはディレクトリ名や、それがファイルかどうか、それがディレクトリかどうかなどの情報を「属性」としてまとめた「エントリ」を列挙するためのイテレータを戻り値とする。そのため、ディレクトリに含まれているエントリ(ファイルやディレクトリの総称)が、ファイルかディレクトリかなどは、is_fileメソッドやis_dirメソッドを使って調べられるようになっている。
実行結果を以下に示す。
Pythonのドキュメント「os.listdir()」では「ディレクトリエントリに加えてファイル属性情報も返す scandir() 関数の方が、多くの一般的な用途では使い勝手が良くなります」とあることから、ファイルやディレクトリの一覧を取得してから、さらにそれらの属性を調べて、その結果に応じた処理を行うような場合には、os.listdir関数ではなくos.scandir関数を使う方がよいだろう(OSレベルのシステムコールを呼び出す回数が減り、パフォーマンス面で有利)。
ディレクトリを新規に作成するには、os.mkdir関数とos.makedirs関数を使える。
os.mkdir(path)
os.makedirs(path)
pathで表されるディレクトリを新規に作成する。指定した名前のファイルまたはディレクトリが既に存在しているときにはFileExistsError例外が発生する。pathで表されるディレクトリパスの途中に存在しないディレクトリがあるときには、os.mkdir関数はFileNotFoundError例外を発生する。os.makedirs関数は存在しないディレクトリを含めて、pathが示すディレクトリを新規に作成する。
パラメーター | 説明 |
---|---|
path | 新規に作成するディレクトリのパス |
os.mkdir関数/os.makedirs関数のパラメーター |
以下にos.mkdir関数を利用するコードの例を示す。
os.mkdir('foo') # カレントディレクトリにfooディレクトリを作成
os.mkdir('foo/bar/baz') # エラー
これを実行すると次のようになる。
最初の行でfooディレクトリを作成したが、作成直後なので、そのディレクトリは空でbarディレクトリは含まれていない。そのため、次の行で「foo/bar/baz」ディレクトリを作成しようとして、例外が発生している。
これに対して、os.makedirs関数では存在しないディレクトリがあっても、それを含めてpathで表されるディレクトリを作成してくれる。以下に例を示す。
os.makedirs('foo/bar/baz')
os.chdir('foo/bar/baz')
print(os.getcwd())
os.chdir('../../..')
print(os.getcwd())
実行結果を以下に示す。foo/bar/bazディレクトリに移動できたことを確認しよう。
Copyright© Digital Advantage Corp. All Rights Reserved.