torinaブログ

DjangoとBootstrap4で作成したブログ
Python, Django, Kivy, Bootstrap, Apache等のメモです
ソースコード

Python、os.path.walkでディレクトリ走査

Python Python標準ライブラリ
2016年6月14日20:26


ディレクトリツリー以下のファイル名を、ツリーをトップダウンもしくはボトムアップに走査することで作成します。
ディレクトリ top を根に持つディレクトリツリーに含まれる、各ディレクトリ (top 自身を含む ) ごとに、
タプル (dirpath, dirnames, filenames) を yield します。



早速使ってみましょう。
以下のようなディレクトリの構成です。
testpython
    ┗main.py
    ┗a.py
    ┗b.py
    ┗folderA
        ┗innerA
        ┗c.py
        ┗d.py
    ┗folderB
        ┗e.py
        ┗f.py


testpythonディレクトリの直下に、main.py、a.py、b.py、folerA、folerB
folderAの中には、innerA、c.py、d.py
folderBの中には、e.py、f.py
です。


import os

current_dir = os.path.dirname(os.path.abspath(__file__))

for root, dirs, files in os.walk(current_dir):
    print("{0}を検索しています...".format(root))
    for dr in dirs:
        print("{0}というディレクトリがあります".format(dr))   
    for file in files:
        print("{0}というファイルがあります".format(file))
    print()  # わかりやすくするための改行、区切り


結果
C:\MyMercurial\test\testpythonを検索しています...
folderAというディレクトリがあります
folderBというディレクトリがあります
a.pyというファイルがあります
b.pyというファイルがあります
main.pyというファイルがあります

C:\MyMercurial\test\testpythonolderAを検索しています...
innnerAというディレクトリがあります
c.pyというファイルがあります
d.pyというファイルがあります

C:\MyMercurial\test\testpythonolderA\innnerAを検索しています...

C:\MyMercurial\test\testpythonolderBを検索しています...
e.pyというファイルがあります
f.pyというファイルがあります


これは、実行ファイル(main.py)の絶対パスを取得し、その親のディレクトリパスを取得しています。
もっと単純な方法もありますが、実行ファイルや実行ディレクトリの絶対パスが欲しい場合は、このように行うと良いでしょう。
current_dir = os.path.dirname(os.path.abspath(__file__))


os.walkにパスを与えると、そのパスからディレクトリツリーを走査してくれます。
for root, dirs, files in os.walk(current_dir):


このような相対パスの指定もできます。
for root, dirs, files in os.walk("folderA"):


カレントディレクトリなら、実はもっと単純に行えます。
# カレント
for root, dirs, files in os.walk("."):

# 親
for root, dirs, files in os.walk(".."):



シンボリックリンクを辿りたい場合は、以下のように
for root, dirs, files in os.walk(current_dir, followlinks=True):


ボトムアップ...例えば、最初にinnerAディレクトリから表示し、最期にtestpythonディレクトリを表示するならばtopdown=Falseとします。
for root, dirs, files in os.walk(current_dir, topdown=False):


結果
C:\MyMercurial\test\testpythonolderA\innnerAを検索しています...

C:\MyMercurial\test\testpythonolderAを検索しています...
innnerAというディレクトリがあります
c.pyというファイルがあります
d.pyというファイルがあります

C:\MyMercurial\test\testpythonolderBを検索しています...
e.pyというファイルがあります
f.pyというファイルがあります

C:\MyMercurial\test\testpythonを検索しています...
folderAというディレクトリがあります
folderBというディレクトリがあります
a.pyというファイルがあります
b.pyというファイルがあります
main.pyというファイルがあります


以下のコードは、pythonファイルの場合(.pyがファイル名に含まれている)はそのパスを表示するコードです。
import os

current_dir = os.path.dirname(os.path.abspath(__file__))

for root, dirs, files in os.walk(current_dir):
    for file in files:
        if ".py" in file:
            path = os.path.join(root, file)
            print(path)


結果
C:\MyMercurial\test\testpython.py
C:\MyMercurial\test\testpython.py
C:\MyMercurial\test\testpython\main.py
C:\MyMercurial\test\testpythonolderA\c.py
C:\MyMercurial\test\testpythonolderA\d.py
C:\MyMercurial\test\testpythonolderB\e.py
C:\MyMercurial\test\testpythonolderB.py



以下は、「A」という文字列がが含まれているディレクトリのパスを返します。
import os

current_dir = os.path.dirname(os.path.abspath(__file__))

for root, dirs, files in os.walk(current_dir):
    for dr in dirs:
        if "A" in dr:
            path = os.path.join(root, dr)
            print(path)


結果
C:\MyMercurial\test\testpythonolderA
C:\MyMercurial\test\testpythonolderA\innnerA


ディレクトリの合計サイズを調べるならば、例えば以下のようになります。
import os

current_dir = os.path.dirname(os.path.abspath(__file__))
total_size = 0

for root, dirs, files in os.walk(current_dir):

    files_path = (os.path.join(root, file) for file in files)
    files_size = sum(os.path.getsize(path) for path in files_path)

    print("{0}のファイル合計サイズ:{1}".format(root, files_size))

    total_size += files_size

print("全ての合計", total_size)



結果
C:\MyMercurial\test\testpythonのファイル合計サイズ:433
C:\MyMercurial\test\testpythonolderAのファイル合計サイズ:110
C:\MyMercurial\test\testpythonolderA\innnerAのファイル合計サイズ:0
C:\MyMercurial\test\testpythonolderBのファイル合計サイズ:36
全ての合計 579


参考
http://docs.python.jp/3.5/library/os.html