11.10. shutil — 高水準のファイル操作

ソースコード: Lib/shutil.py


shutil モジュールはファイルやファイルの集まりに対する高水準の操作方法を多数提供します。特にファイルのコピーや削除のための関数が用意されています。個別のファイルに対する操作については、 os モジュールも参照してください。

警告

高水準のファイルコピー関数 (shutil.copy(), shutil.copy2()) でも、ファイルのメタデータの全てをコピーすることはできません。

POSIXプラットフォームでは、これはACLやファイルのオーナー、グループが失われることを意味しています。 Mac OSでは、リソースフォーク(resource fork)やその他のメタデータが利用されません。これは、リソースが失われ、ファイルタイプや生成者コード(creator code)が正しくなくなることを意味しています。 Windowsでは、ファイルオーナー、ACL、代替データストリームがコピーされません。

11.10.1. ディレクトリとファイルの操作

shutil.copyfileobj(fsrc, fdst[, length])

ファイル形式のオブジェクト fsrc の内容を fdst へコピーします。整数値 length は与えられた場合バッファサイズを表します。特に length が負の場合、チャンク内のソースデータを繰り返し操作することなくデータをコピーします。デフォルトでは、制御不能なメモリ消費を避けるためにデータはチャンク内に読み込まれます。 fsrc オブジェクトの現在のファイル位置が0でない場合、現在の位置からファイル終端までの内容のみがコピーされることに注意してください。

shutil.copyfile(src, dst, *, follow_symlinks=True)

src という名前のファイルの内容 (メタデータを含まない) を dst という名前のファイルにコピーし、dst を返します。 srcdst は文字列でパス名を指定します。 dst は完全な対象ファイル名でなければなりません。対象としてディレクトリ名を指定したい場合は shutil.copy() を参照してください。 srcdst が同じファイルだった場合、 SameFileError を送出します。

dst は書き込み可能でなければなりません。そうでない場合、 OSError 例外を送出します。 dst がすでに存在する場合、そのファイルは置き換えられます。キャラクタデバイスやブロックデバイスなどの特殊なファイルとパイプをこの関数でコピーすることはできません。

follow_symlinks が偽で src がシンボリックリンクの場合、 src のリンク先をコピーする代わりに新しいシンボリックリンクを作成します。

バージョン 3.3 で変更: 以前は OSError の代わりに IOError が送出されていました。 follow_symlinks 引数が追加されました。 dst を返すようになりました。

バージョン 3.4 で変更: Error の代わりに SameFileError を送出します。後者は前者のサブクラスなのでこの変更は後方互換です。

exception shutil.SameFileError

copyfile() のコピー元と先が同じファイルの場合送出されます。

バージョン 3.4 で追加.

shutil.copymode(src, dst, *, follow_symlinks=True)

パーミッションを src から dst にコピーします。ファイルの内容、オーナー、グループには影響しません。 srcdst は文字列でファイルのパス名を指定します。 follow_symlinks が偽で、src および dst がシンボリックリンクの場合、 copymode() は (リンク先ではなく) dst 自体のモードを変更します。この機能は全てのプラットフォームで使えるわけではありません。詳しくは copystat() を参照してください。シンボリックリンクの変更をしようとした時、 copymode() がローカルのプラットフォームでシンボリックリンクを変更できない場合は何もしません。

バージョン 3.3 で変更: follow_symlinks 引数が追加されました。

shutil.copystat(src, dst, *, follow_symlinks=True)

パーミッション、最終アクセス時間、最終変更時間、その他のフラグを src から dst にコピーします。 Linux では、 copystat() は可能なら “拡張属性” もコピーします。ファイルの内容、オーナー、グループには影響しません。 srcdst は文字列でファイルのパス名を指定します。

follow_symlinks が偽の場合、 srcdst の両方がシンボリックリンクであれば、 copystat() はリンク先ではなくてシンボリックリンク自体を操作します。 src からシンボリックリンクの情報を読み込み、 dst のシンボリックリンクにその情報を書き込みます。

注釈

すべてのプラットフォームでシンボリックリンクの検査と変更ができるわけではありません。 Python はその機能が利用かどうかを調べる方法を用意しています。

  • os.chmod in os.supports_follow_symlinksTrue の場合 copystat() はシンボリックリンクのパーミッションを変更できます。

  • os.utime in os.supports_follow_symlinksTrue の場合 copystat() はシンボリックリンクの最終アクセス時間と最終変更時間を変更できます。

  • os.chflags in os.supports_follow_symlinksTrue の場合 copystat() はシンボリックリンクのフラグを変更できます。 (os.chflags がないプラットフォームもあります。)

機能の幾つか、もしくは全てが利用できないプラットフォームでシンボリックリンクを変更しようとした場合、 copystat() は可能な限り全てをコピーします。copystat() が失敗を返すことはありません。

より詳しい情報は os.supports_follow_symlinks を参照して下さい。

バージョン 3.3 で変更: follow_symlinks 引数と Linux の拡張属性がサポートされました。

shutil.copy(src, dst, *, follow_symlinks=True)

ファイル src をファイルまたはディレクトリ dst にコピーします。 srcdst は両方共文字列でなければなりません。 dst がディレクトリを指定している場合、ファイルは dst の中に、 src のベースファイル名を使ってコピーされます。新しく作成したファイルのパスを返します。

follow_symlinks が偽で、 src がシンボリックリンクの場合、 dst はシンボリックリンクとして作成されます。 follow_symlinks が真で src がシンボリックリンクの場合、 dst には src のリンク先のファイルがコピーされます。

copy() はファイルのデータとパーミッションをコピーします。 (os.chmod() を参照) その他の、ファイルの作成時間や変更時間などのメタデータはコピーしません。 コピー元のファイルのメタデータを保存したい場合は、 copy2() を利用してください。

バージョン 3.3 で変更: follow_symlinks 引数が追加されました。新しく作成されたファイルのパスを返すようになりました。

shutil.copy2(src, dst, *, follow_symlinks=True)

copy2() はファイルの全てのメタデータを保持しようとすることを除けば copy() と等価です。

follow_symlinks が偽で、 src がシンボリックリンクの場合、 copy2()src のシンボリックリンクからすべてのメタデータを新規に作成した dst のシンボリックリンクにコピーしようとします。しかしながら、この機能は全てのプラットフォームで利用できるわけではありません。機能の幾つか、もしくは全てが利用できないプラットフォームの場合、 copy2() は可能な限り全てのメタデータをコピーします。copy2() が失敗を返すことはありません。

copy2() はファイルのメタデータをコピーするために copystat() を利用します。シンボリックリンクのメタデータを変更するためのプラットフォームサポートについては copystat() を参照して下さい。

バージョン 3.3 で変更: follow_symlinks 引数が追加されました。 拡張ファイルシステム属性もコピーしようと試みます (現在は Linux のみ)。新しく作成されたファイルへのパスを返すようになりました。

shutil.ignore_patterns(*patterns)

このファクトリ関数は、 copytree() 関数の ignore 引数に渡すための呼び出し可能オブジェクトを作成します。 glob形式の patterns にマッチするファイルやディレクトリが無視されます。下の例を参照してください。

shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False)

src をルートにしたディレクトリツリー全体をコピーして、コピー先ディレクトリを返します。コピー先ディレクトリ dst は事前に存在していてはならず、足りない親ディレクトリと合わせて作成されます。ディレクトリの各種時間やパーミッションは copystat() でコピーし、各ファイルは shutil.copy2() でコピーします。

symlinks が真の場合、ソースツリー内のシンボリックリンクは新しいツリーでもシンボリックになり、元のシンボリックリンクのメタデータはプラットフォームが許す限りコピーされます。偽の場合や省略された場合、リンク先のファイルの内容とメタデータが新しいツリーにコピーされます。

symlinks が偽の場合、リンク先のファイルが存在しなければ、コピー処理終了時に送出される Error 例外のエラーリストに例外が追加されます。オプションの ignore_dangling_symlinks フラグを真に設定してこのエラーを送出させないこともできます。このオプションは os.symlink() をサポートしていないプラットフォーム上では効果がないことに注意してください。

ignorecopytree() が走査しているディレクトリと os.listdir() が返すその内容のリストを引数として受け取ることのできる呼び出し可能オブジェクトでなければなりません。 copytree() は再帰的に呼び出されるので、 ignore はコピーされる各ディレクトリ毎に呼び出されます。 ignore の戻り値はカレントディレクトリに相対的なディレクトリ名およびファイル名のシーケンス(すなわち第二引数の項目のサブセット)でなければなりません。それらの名前はコピー中に無視されます。 ignore_patterns() を用いて glob 形式のパターンによって無視する呼び出し可能オブジェクトを作成することが出来ます。

例外が発生した場合、理由のリストとともに Error を送出します。

copy_function は各ファイルをコピーするために利用される呼び出し可能オブジェクトでなければなりません。copy_function はコピー元のパスとコピー先のパスを引数に呼び出されます。デフォルトでは shutil.copy2() が利用されますが、同じ特徴を持つ関数 (shutil.copy() など) ならどれでも利用可能です。

バージョン 3.3 で変更: symlinks が偽の場合メタデータをコピーします。 dst を返すようになりました。

バージョン 3.2 で変更: カスタムコピー機能を提供できるように copy_function 引数が追加されました。 symlinks が偽の時にダングリング (宙ぶらりんの) シンボリックリンクエラーを送出させないために ignore_dangling_symlinks 引数が追加されました。

shutil.rmtree(path, ignore_errors=False, onerror=None)

ディレクトリツリー全体を削除します。 path はディレクトリを指していなければなりません (ただしディレクトリに対するシンボリックリンクではいけません)。ignore_errors が真である場合、削除に失敗したことによるエラーは無視されます。偽や省略された場合はこれらのエラーは onerror で与えられたハンドラを呼び出して処理され、onerror が省略された場合は例外を送出します。

注釈

必要な fd ベースの関数をサポートしているプラットフォームでは、 シンボリックリンク攻撃に耐性のあるバージョンの rmtree() がデフォルトで利用されます。それ以外のプラットフォームでは、 rmtree() の実装はシンボリックリンク攻撃の影響を受けます。適当なタイミングと環境で攻撃者はファイルシステム上のシンボリックリンクを操作して、それ以外の方法ではアクセス不可能なファイルを削除することが出来ます。アプリケーションは、どちらのバージョンの rmtree() が利用されているかを知るために関数のデータ属性 rmtree.avoids_symlink_attacks を利用することができます。

onerror を指定する場合、 function, path, excinfo の3つの引数を受け取る呼び出し可能オブジェクトでなければなりません。

最初の引数 function は例外を送出した関数で、プラットフォームや実装に依存します。第二引数 pathfunction に渡されたパス名です。第三引数 excinfosys.exc_info() が返した例外の情報です。 onerror が送出した例外は捕捉されません。

バージョン 3.3 で変更: プラットフォームが fd ベースの関数をサポートする場合に自動的に使用されるシンボリックリンク攻撃に耐性のあるバージョンが追加されました。

プラットフォームと実装がシンボリックリンク攻撃に耐性のあるバージョンの rmtree() を提供しているかどうかを示します。現在のところ、この属性は fd ベースのディレクトリアクセス関数をサポートしているプラットフォームでのみ真になります。

バージョン 3.3 で追加.

shutil.move(src, dst, copy_function=copy2)

ファイルまたはディレクトリ (src) を再帰的に別の場所 (dst) に移動して、移動先を返します。

移動先が存在するディレクトリの場合、 src はそのディレクトリの中へ移動します。移動先が存在していてそれがディレクトリでない場合、 os.rename() の動作によっては上書きされることがあります。

ターゲットが現在のファイルシステム上にある場合、 os.rename() が使用されます。 それ以外の場合 copy_function を使用して srcdst にコピーし、その後削除します。 シンボリックリンクの場合には、 src のターゲットを指す新しいシンボリックリンクが、 dst の中または dst として作成され、 src が削除されます。

copy_function を指定する場合、 srcdst の 2 つの引数を持つ呼び出し可能オブジェクトを指定する必要があります。このオブジェクトは、os.rename() を使用できない場合に srcdest にコピーするために使用されます。ソースがディレクトリの場合、 copytree() が呼び出され、そのディレクトリを copy_function() に渡します。デフォルトの copy_functioncopy2() です。copy()copy_function として使用すると、メタデータをともにコピーすることができない場合に移動を成功させることができます。この場合、メタデータはまったくコピーされません。

バージョン 3.3 で変更: 異なるファイルシステムに対する明示的なシンボリックリンク処理が追加されました。これにより GNU mv の振る舞いに適応するようになります。 dst を返すようになりました。

バージョン 3.5 で変更: キーワード引数 copy_function が追加されました。

shutil.disk_usage(path)

指定されたパスについて、ディスクの利用状況を、名前付きタプル (named tuple) で返します。このタプルには total, used, free という属性があり、それぞれトータル、使用中、空きの容量をバイト単位で示します。

バージョン 3.3 で追加.

利用できる環境 : Unix 、 Windows 。

shutil.chown(path, user=None, group=None)

指定された path のオーナー user と/または group を変更します。

user はシステムのユーザー名か uid です。 group も同じです。少なくともどちらかの引数を指定する必要があります。

内部で利用している os.chown() も参照してください。

利用できる環境 : Unix 。

バージョン 3.3 で追加.

shutil.which(cmd, mode=os.F_OK | os.X_OK, path=None)

cmd を実行しようとした時に実行される実行ファイルのパスを返します。 cmd を呼び出せない場合は None を返します。

modeos.access() に渡すパーミッションマスクで、デフォルトではファイルが存在して実行可能であることを確認します。

path が指定されなかった場合、 os.environ() が利用され、 “PATH” の値を返すか os.defpath にフォールバックします。

Windows では、 path を指定した場合もデフォルト値を使った場合も、カレントディレクトリが最初に探されます。これはコマンドシェルが実行ファイルを探すときの動作です。また、 cmdpath から検索するときに、 PATHEXT 環境変数も利用します。例えば、 shutil.which("python") を実行した場合、 which()PATHEXT を参照して path ディレクトリから python.exe を探すべきだということを把握します。例えば、 Windows では:

>>> shutil.which("python")
'C:\\Python33\\python.EXE'

バージョン 3.3 で追加.

exception shutil.Error

この例外は複数ファイルの操作を行っているときに生じる例外をまとめたものです。 copytree() に対しては例外の引数は3つのタプル(srcname, dstname, exception)からなるリストです。

11.10.1.1. copytree の例

以下は前述の copytree() 関数のドキュメント文字列を省略した実装例です。本モジュールで提供される他の関数の使い方を示しています。

def copytree(src, dst, symlinks=False):
    names = os.listdir(src)
    os.makedirs(dst)
    errors = []
    for name in names:
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        try:
            if symlinks and os.path.islink(srcname):
                linkto = os.readlink(srcname)
                os.symlink(linkto, dstname)
            elif os.path.isdir(srcname):
                copytree(srcname, dstname, symlinks)
            else:
                copy2(srcname, dstname)
            # XXX What about devices, sockets etc.?
        except OSError as why:
            errors.append((srcname, dstname, str(why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except Error as err:
            errors.extend(err.args[0])
    try:
        copystat(src, dst)
    except OSError as why:
        # can't copy file access times on Windows
        if why.winerror is None:
            errors.extend((src, dst, str(why)))
    if errors:
        raise Error(errors)

ignore_patterns() ヘルパ関数を利用する、もう1つの例です。

from shutil import copytree, ignore_patterns

copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))

この例では、 .pyc ファイルと、 tmp で始まる全てのファイルやディレクトリを除いて、全てをコピーします。

ignore 引数にロギングさせる別の例です。

from shutil import copytree
import logging

def _logpath(path, names):
    logging.info('Working in %s', path)
    return []   # nothing will be ignored

copytree(source, destination, ignore=_logpath)

11.10.1.2. rmtree の例

次の例は、Windows で一部のファイルが読み込み専用のビットセットを含む場合に、ディレクトリツリーを削除する方法を示します。onerror コールバックを使用して、読み込み専用のビットを消去し、削除を再試行します。結果として失敗が発生した場合、それらは伝搬されます:

import os, stat
import shutil

def remove_readonly(func, path, _):
    "Clear the readonly bit and reattempt the removal"
    os.chmod(path, stat.S_IWRITE)
    func(path)

shutil.rmtree(directory, onerror=remove_readonly)

11.10.2. アーカイブ化操作

バージョン 3.2 で追加.

バージョン 3.5 で変更: xztar 形式のサポートが追加されました。

圧縮とアーカイブ化されているファイルの読み書きの高水準なユーティリティも提供されています。これらは zipfiletarfile モジュールに依拠しています。

shutil.make_archive(base_name, format[, root_dir[, base_dir[, verbose[, dry_run[, owner[, group[, logger]]]]]]])

アーカイブファイル (zip や tar) を作成してその名前を返します。

base_name は、作成するファイルの、パスを含み、フォーマットごとの拡張子を抜いた名前です。 format はアーカイブフォーマットで “zip” (zlib モジュールが利用可能な場合), “tar”, “gztar” (zlib モジュールが利用可能な場合), “bztar” (bz2 モジュールが利用可能な場合), “xztar” (lzma モジュールが利用可能な場合) のいずれかです。

root_dir は、アーカイブのルートディレクトリとなるディレクトリです。例えば、一般的には、アーカイブを作成する前に root_dir をカレントディレクトリにします。

base_dir は、アーカイブを開始するディレクトリです。すなわち、 base_dir は、アーカイブのすべてのファイルとディレクトリに共通する接頭辞になります。

root_dirbase_dir のどちらも、デフォルトはカレントディレクトリです。

dry_run が真の場合、アーカイブは作成されませんが実行される操作は logger に記録されます。

ownergroup は、tar アーカイブを作成するときに使われます。デフォルトでは、カレントのオーナーとグループを使います。

loggerPEP 282 に互換なオブジェクトでなければなりません。これは普通は logging.Logger のインスタンスです。

verbose 引数は使用されず、非推奨です。

shutil.get_archive_formats()

アーカイブ化をサポートしているフォーマットのリストを返します。返されるシーケンスのそれぞれの要素は、タプル (name, description) です。

デフォルトでは、 shutil は次のフォーマットを提供しています。

  • zip: ZIP ファイル (zlib モジュールが利用可能な場合)。

  • tar: 圧縮されていない tar ファイル。

  • gztar: gzip で圧縮された tar ファイル (zlib モジュールが利用可能な場合)。

  • bztar: bzip2 で圧縮された tar ファイル (bz2 モジュールが利用可能な場合)。

  • xztar: xz で圧縮された tar ファイル (lzma モジュールが利用可能な場合)。

register_archive_format() を使って、新しいフォーマットを登録したり、既存のフォーマットに独自のアーカイバを提供したりできます。

shutil.register_archive_format(name, function[, extra_args[, description]])

アーカイバをフォーマット name に登録します。

function はアーカイブのアンパックに使用される呼び出し可能オブジェクトです。funciton は作成するファイルの base_name、続いてアーカイブを開始する元の base_dir (デフォルトは os.curdir) を受け取ります。さらなる引数は、次のキーワード引数として渡されます: owner, group, dry_run ならびに logger (make_archive() に渡されます)。

extra_args は、与えられた場合、 (name, value) の対のシーケンスで、アーカイバ呼び出し可能オブジェクトが使われるときに追加のキーワード引数として使われます。

description は、アーカイバのリストを返す get_archive_formats() で使われます。デフォルトでは空の文字列です。

shutil.unregister_archive_format(name)

アーカイブフォーマット name を、サポートされているフォーマットのリストから取り除きます。

shutil.unpack_archive(filename[, extract_dir[, format]])

アーカイブをアンパックします。 filename はアーカイブのフルパスです。

extract_dir はアーカイブをアンパックする先のディレクトリ名です。指定されなかった場合は現在の作業ディレクトリを利用します。

format はアーカイブフォーマットで、 “zip”, “tar”, “gztar”, “bztar”, “xztar” あるいは register_unpack_format() で登録したその他のフォーマットのどれかです。 指定されなかった場合、 unpack_archive() はアーカイブファイル名の拡張子に対して登録されたアンパッカーを利用します。 アンパッカーが見つからなかった場合、 ValueError を発生させます。

shutil.register_unpack_format(name, extensions, function[, extra_args[, description]])

アンパック用のフォーマットを登録します。 name はフォーマット名で、 extensions はそのフォーマットに対応する拡張子 (例えば Zip ファイルに対して .zip) のリストです。

function はアーカイブをアンパックするための呼び出し可能オブジェクトです。このオブジェクトはアーカイブのパスと、アーカイブを展開するディレクトリのパスを引数に受け取ります。

extra_args は省略可能な引数で、呼び出し可能オブジェクトに渡すキーワード引数を (name, value) というタプルのシーケンスにしたものです。

フォーマットの説明として description を指定することができます。これは get_unpack_formats() 関数によって返されます。

shutil.unregister_unpack_format(name)

アンパックフォーマットを登録解除します。 name はフォーマットの名前です。

shutil.get_unpack_formats()

登録されているすべてのアンパックフォーマットをリストで返します。戻り値のリストの各要素は (name, extensions, description) の形のタプルです。

デフォルトでは、 shutil は次のフォーマットを提供しています。

  • zip: ZIP ファイル (対応するモジュールが利用可能な場合にのみ圧縮ファイルはアンパックされます)。

  • tar: 圧縮されていない tar ファイル。

  • gztar: gzip で圧縮された tar ファイル (zlib モジュールが利用可能な場合)。

  • bztar: bzip2 で圧縮された tar ファイル (bz2 モジュールが利用可能な場合)。

  • xztar: xz で圧縮された tar ファイル (lzma モジュールが利用可能な場合)。

register_unpack_format() を使って新しいフォーマットや既存のフォーマットに対する別のアンパッカーを登録することができます。

11.10.2.1. アーカイブ化の例

この例では、ユーザの .ssh ディレクトリにあるすべてのファイルを含む、 gzip された tar ファイルアーカイブを作成します:

>>> from shutil import make_archive
>>> import os
>>> archive_name = os.path.expanduser(os.path.join('~', 'myarchive'))
>>> root_dir = os.path.expanduser(os.path.join('~', '.ssh'))
>>> make_archive(archive_name, 'gztar', root_dir)
'/Users/tarek/myarchive.tar.gz'

結果のアーカイブは、以下のものを含みます:

$ tar -tzvf /Users/tarek/myarchive.tar.gz
drwx------ tarek/staff       0 2010-02-01 16:23:40 ./
-rw-r--r-- tarek/staff     609 2008-06-09 13:26:54 ./authorized_keys
-rwxr-xr-x tarek/staff      65 2008-06-09 13:26:54 ./config
-rwx------ tarek/staff     668 2008-06-09 13:26:54 ./id_dsa
-rwxr-xr-x tarek/staff     609 2008-06-09 13:26:54 ./id_dsa.pub
-rw------- tarek/staff    1675 2008-06-09 13:26:54 ./id_rsa
-rw-r--r-- tarek/staff     397 2008-06-09 13:26:54 ./id_rsa.pub
-rw-r--r-- tarek/staff   37192 2010-02-06 18:23:10 ./known_hosts

11.10.3. 出力ターミナルのサイズの取得

shutil.get_terminal_size(fallback=(columns, lines))

ターミナルウィンドウのサイズを取得します。

幅と高さについて、それぞれ COLUMNSLINES という環境変数をチェックします。その変数が定義されていて値が正の整数であればそれを利用します。

典型的な COLUMNSLINES が定義されていない場合には、 sys.__stdout__ に接続されているターミナルに os.get_terminal_size() を呼び出して問い合わせます。

システムが対応していない場合やターミナルに接続していないなどの理由でターミナルサイズの問い合わせに失敗した場合、 fallback 引数に与えられた値を利用します。 fallback のデフォルト値は (80, 24) で、これは多くのターミナルエミュレーターが利用しているデフォルトサイズです。

戻り値は os.terminal_size 型の名前付きタプルです。

参考: The Single UNIX Specification, Version 2, Other Environment Variables.

バージョン 3.3 で追加.