目次

前のトピックへ

11.9. linecache — テキストラインにランダムアクセスする

次のトピックへ

11.11. dircache — キャッシュされたディレクトリ一覧の生成

このページ

11.10. shutil — 高レベルなファイル操作

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

警告

高レベルなファイルコピー関数(copy(), copy2())でも、全てのファイルの メタデータをコピーできるわけではありません。

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

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

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

shutil.copyfile(src, dst)

src で指定されたファイルの内容を dst で指定されたファイルへとコピーします。(メタデータはコピーされません) dst は完全なターゲットファイル名である必要があります。 コピー先にディレクトリ名を使用したい場合は、 copy() を参照してください。 もし、 srcdst が同じファイルであれば、 Error 例外が発生します。

コピー先は書き込み可能である必要があります。そうでなければ IOError を発生します。もし dst が存在したら、置き換えられます。 キャラクタやブロックデバイス、パイプ等の特別なファイルはこの関数ではコピーできません。 srcdst にはパス名を文字列で与えられます。

shutil.copymode(src, dst)

src から dst へパーミッションをコピーします。ファイル内容や所有者、グループは影響を受けません。 srcdst には文字列としてパス名を与えられます。

shutil.copystat(src, dst)

src から dst へ、パーミッション、最終アクセス時間、最終更新時間、フラグをコピーします。 ファイル内容や所有者、グループは影響を受けません。 srcdst には文字列としてパス名を与えられます。

shutil.copy(src, dst)

ファイル src をファイルまたはディレクトリ dist へコピーします。もし、 dst がディレクトリであればファイル名は src と同じものが 指定されたディレクトリ内に作成(または上書き)されます。パーミッションはコピーされます。 srcdst には文字列としてパス名を与えられます。

shutil.copy2(src, dst)

copy() と類似していますが、メタデータも同様にコピーされます。 実際のところ、この関数は copy() の後に copystat() しています。 Unix コマンドの cp -p と同様の働きをします。

shutil.ignore_patterns(*patterns)

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

バージョン 2.6 で追加.

shutil.copytree(src, dst[, symlinks])

src を起点としたディレクトリツリーをコピーします。 dst で指定されたターゲットディレクトリは、既存のもので無い必要があります。 存在しない親ディレクトリも含めて作成されます。パーミッションと時刻は copystat() 関数でコピーされます。個々のファイルは copy2() によってコピーされます。

symlinks が真であれば、元のディレクトリ内のシンボリックリンクはコピー先のディレクトリ内へシンボリックリンクとして コピーされます。偽が与えられたり省略された場合は元のディレクトリ内のリンクの対象となっているファイルがコピー先のディレクトリ内へコピーされま す。

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

エラーが発生したときはエラー理由のリストを持った Error を起こします。

この関数は、究極の道具としてではなく、ソースコードが利用例になっていると捉えるべきでしょう。

バージョン 2.3 で変更: コピー中にエラーが発生した場合、メッセージを出力するのではなく Error を起こす。

バージョン 2.5 で変更: dst を作成する際に中間のディレクトリ作成が必要な場合、エラーを起こすのではなく作成する。ディレクトリのパーミッションと時刻を copystat() を利用してコピーする。

バージョン 2.6 で変更: 何がコピーされるかを制御するための ignore 引数

shutil.rmtree(path[, ignore_errors[, onerror]])

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

onerror が与えられた場合、それは3つのパラメータ function, path および excinfo を受け入れて呼び出し可能のものでなくてはな りません。最初のパラメータ function は例外を引き起こした関数で os.listdir(), os.remove(), os.rmdir() のいずれかでしょう。 2番目のパラメータ pathfunction へ渡されたパス名です。 3番目のパラメータ excinfosys.exc_info() で返されるよ うな例外情報になるでしょう。 onerror が引き起こす例外はキャッチできません。

バージョン 2.6 で変更: .. Explicitly check for path being a symbolic link and raise OSError in that case.

path を明示的にチェックして、シンボリックリンクだった場合は OSError を返すようになりました。

shutil.move(src, dst)

再帰的にファイルやディレクトリを別の場所へ移動します。

もし移動先が現在のファイルシステム上であれば単純に名前を変更します。 そうでない場合は(copy2() で)コピーを行い、その後コピー元は削除されます。

バージョン 2.3 で追加.

exception shutil.Error

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

バージョン 2.3 で追加.

11.10.1. 使用例

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

def copytree(src, dst, symlinks=False, ignore=None):
    names = os.listdir(src)
    if ignore is not None:
        ignored_names = ignore(src, names)
    else:
        ignored_names = set()

    os.makedirs(dst)
    errors = []
    for name in names:
        if name in ignored_names:
            continue
        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, ignore)
            else:
                copy2(srcname, dstname)
            # XXX What about devices, sockets etc.?
        except (IOError, os.error), why:
            errors.append((srcname, dstname, str(why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except Error, err:
            errors.extend(err.args[0])
    try:
        copystat(src, dst)
    except WindowsError:
        # can't copy file access times on Windows
        pass
    except OSError, why:
        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)