Pythonの基本 ファイルツリーの取得

f:id:wataru_boss:20180527172045p:plain
こんにちは。BOSSです。

ある特定のディレクトリー内のファイルを一括して扱いたい。

そういったときに、ファイル名を一つずつ入力していくのは非常に効率が悪いですよね。

特にファイルがいくつもいくつもある場合はとても手作業でやるべきことではありません。

そういう場合はファイルツリーを取得すれば解決します。

ファイルツリーのイメージはこんな感じ。

root/
  |__ Applications/
  |__ usr/
        |__ username/
              |__ Documents/
              |__ Downloads/
              |__ Music/
              |__ Picures/

Pythonではosモジュールを用いることでこういったファイルツリーの情報を取得することができます。

したがって以下の内容はまずosモジュールのimportから始まります。

import os

本記事ではファイルツリーの取得の仕方や使い方についてまとめておこうかと思います。

os.listdir()

ある特定のディレクトリー内のディレクトリーとファイルの一覧はlistdir関数を用いることで取得できます。

記述の仕方は以下の通り。

import os

listの変数 = os.listdir('ディレクトリーパス')

もう少し実用的に、ディレクトリー内のリストを表示する関数にしてみましょう。

import os

def directory_list(target_path):
    for name in os.listdir(target_path):
        print(name)
    
    

if __name__ == '__main__':
    directory_list('ディレクトリーパス')

たとえば以下のようなディレクトリー内の一覧を表示して見ます。これはこのブログ内で紹介してるプログラムがまとまっているディレクトリーです。

f:id:wataru_boss:20180522125254p:plain

そうするとこんな結果が返ってきます。

/Users/boss/PycharmProjects/blog_code/venv/bin/python /Users/boss/PycharmProjects/blog_code/listdir()_example.py
lunch.csv
.DS_Store
average_function.py
listdir()_example.py
Mode.py
Median.py
file_open_write.py
average_temperature.py
venv
.idea

Process finished with exit code 0

.DS_Storeと.ideaは隠しファイルですが、それ以外は見えている通りの結果となっています。

os.walk()

os.listdir()は特定のディレクトリー内のディレクトリーおよびファイルのリストを作成する関数でした。

ディレクトリー内のさらに下層の孫ディレクトリーの中のファイルなど全てを取得したい場合はos.walkを用います。

基本の記述の仕方は以下の通り。

    for dirpath, dirnames, filenames in os.walk('ディレクトリーパス')

このようにfor文でファイル走査をしていき、値がdirpath, dirnames, filenamesに格納されます。変数名は別になんでもいいですが、ここでは分かりやすいようにこのように設定します。

それぞれどのような値が格納されるのか。以下に記します。

  • dirpath
    指定したディレクトリー内に含まれる、ディレクトリーパスが一つずつ代入されます。

  • dirnames
    指定したディレクトリー内に含まれる、ディレクトリー名がタプルで格納されます。

  • files
    指定したディレクトリー内に含まれる、ファイル名がタプルで格納されます。

さて、では具体的なプログラム例を示しておきます。

import os

def directory_tree(target_path):
    for dirpath, dirnames, filenames in os.walk(target_path):
        print(root)
        for dir in dirs:
            print('\t', dir)
        for file in files:
            print('\t', file)

if __name__ == '__main__':
    directory_tree('ディレクトリーパス')

上記のプログラムによって全ディレクトリーについて1つずつ ディレクトリーパス
ディレクトリー名
ファイル名 が表示されます。だいたいこんな感じ。

/Users/boss/PycharmProjects/blog_code/venv/bin/python /Users/boss/PycharmProjects/blog_code/walk()_example.py
/Users/boss/PycharmProjects/blog_code
     venv
     .idea
     walk()_example.py
     lunch.csv
     .DS_Store
     average_function.py
     listdir()_example.py
     Mode.py
     Median.py
     file_open_write.py
     average_temperature.py
/Users/boss/PycharmProjects/blog_code/venv
     bin
     include
     lib
     .DS_Store
     pyvenv.cfg
/Users/boss/PycharmProjects/blog_code/venv/bin
     pip3.6
     python3
     easy_install
     python
     pip3
     easy_install-3.6
     activate.fish
     pip
     activate
     activate.csh

....etc

ファイルパスを取得する

さきほどまではただ表示するだけのプログラムでしたが、実際にはパスやファイル名が取得できるというのは非常に強力です。

例えば次のように記述すると指定ディレクトリー以下のファイルのフルパスが取得できます。

import os

def search(target_path):
    # ターゲットパス内のファイル、ディレクトリー以下のファイル情報を取得
    for dirpath, dirnames, filenames in os.walk(target_path):
        for file in files:
            file_path = os.path.join(dirpath, file)

ここではos.path.join()という関数を使い、dirpahtとfileつまりディレクトリーのパスとファイル名を結合することでフルパスを取得しているのです。

これができると例えば以下の記述で

import os

def search(target_path):
    # ターゲットパス内のファイル、ディレクトリー以下のファイル情報を取得
    for dirpath, dirnames, filenames in os.walk(target_path):
        for file in files:
            file_path = os.path.join(dirpath, file)
                with open(file_path, encoding = 'utf-8') as f:
......

などとすることでファイルを開いたりすることができます。

まとめ

今回はファイルの探索についてまとめました。

ファイルパスやファイル名の取得が行えたらいろんなファイル操作が行えます。

具体的にはたくさんのファイルに対して同じ処理をしたい場合、このように一気にファイルパス等が取得できないと手で打ち込まないといけなくなります。

まさしく、今作っている途中の実験データ整理プログラムはその問題に直面し解決を図っているところです。

具体的にファイル探索に関してプログラムとして使用するという点はまた記事にしたいと思います。