"shutil" — 高水準のファイル操作
*******************************

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

======================================================================

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

警告: Even the higher-level file copying functions ("shutil.copy()",
  "shutil.copy2()") can’t copy all file metadata.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)

   Copy the contents (no metadata) of the file named *src* to a file
   named *dst*.  *dst* must be the complete target file name; look at
   "shutil.copy()" for a copy that accepts a target directory path.
   If *src* and *dst* are the same files, "Error" is raised. The
   destination location must be writable; otherwise,  an "IOError"
   exception will be raised. If *dst* already exists, it will be
   replaced.   Special files such as character or block devices and
   pipes cannot be copied with this function.  *src* and *dst* are
   path names given as strings.

shutil.copymode(src, dst)

   Copy the permission bits from *src* to *dst*.  The file contents,
   owner, and group are unaffected.  *src* and *dst* are path names
   given as strings.

shutil.copystat(src, dst)

   Copy the permission bits, last access time, last modification time,
   and flags from *src* to *dst*.  The file contents, owner, and group
   are unaffected.  *src* and *dst* are path names given as strings.

shutil.copy(src, dst)

   Copy the file *src* to the file or directory *dst*.  If *dst* is a
   directory, a file with the same basename as *src*  is created (or
   overwritten) in the directory specified.  Permission bits are
   copied.  *src* and *dst* are path names given as strings.

shutil.copy2(src, dst)

   Similar to "shutil.copy()", but metadata is copied as well – in
   fact, this is just "shutil.copy()" followed by "copystat()".  This
   is similar to the Unix command **cp -p**.

shutil.ignore_patterns(*patterns)

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

   バージョン 2.6 で追加.

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

   Recursively copy an entire directory tree rooted at *src*.  The
   destination directory, named by *dst*, must not already exist; it
   will be created as well as missing parent directories.  Permissions
   and times of directories are copied with "copystat()", individual
   files are copied using "shutil.copy2()".

   If *symlinks* is true, symbolic links in the source tree are
   represented as symbolic links in the new tree, but the metadata of
   the original links is NOT copied; if false or omitted, the contents
   and metadata of the linked files are copied to the new tree.

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

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

   The source code for this should be considered an example rather
   than the ultimate tool.

   バージョン 2.3 で変更: "Error" is raised if any exceptions occur
   during copying, rather than printing a message.

   バージョン 2.5 で変更: Create intermediate directories needed to
   create *dst*, rather than raising an error. Copy permissions and
   times of directories using "copystat()".

   バージョン 2.6 で変更: Added the *ignore* argument to be able to
   influence what is being copied.

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

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

   If *onerror* is provided, it must be a callable that accepts three
   parameters: *function*, *path*, and *excinfo*. The first parameter,
   *function*, is the function which raised the exception; it will be
   "os.path.islink()", "os.listdir()", "os.remove()" or "os.rmdir()".
   The second parameter, *path*, will be the path name passed to
   *function*.  The third parameter, *excinfo*, will be the exception
   information return by "sys.exc_info()".  Exceptions raised by
   *onerror* will not be caught.

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

shutil.move(src, dst)

   Recursively move a file or directory (*src*) to another location
   (*dst*).

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

   If the destination is on the current filesystem, then "os.rename()"
   is used.  Otherwise, *src* is copied (using "shutil.copy2()") to
   *dst* and then removed.

   バージョン 2.3 で追加.

exception shutil.Error

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

   バージョン 2.3 で追加.


copytree の例
-------------

以下は前述の "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) 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 WindowsError:
           # can't copy file access times on Windows
           pass
       except OSError as 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)


アーカイブ化操作
================

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

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

   Create an archive file (eg. zip or tar) and returns its name.

   *base_name* is the name of the file to create, including the path,
   minus any format-specific extension. *format* is the archive
   format: one of 「zip」 (if the "zlib" module or external "zip"
   executable is available), 「tar」, 「gztar」 (if the "zlib" module
   is available), or 「bztar」 (if the "bz2" module is available).

   *root_dir* is a directory that will be the root directory of the
   archive; ie. we typically chdir into *root_dir* before creating the
   archive.

   *base_dir* is the directory where we start archiving from; ie.
   *base_dir* will be the common prefix of all files and directories
   in the archive.

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

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

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

   バージョン 2.7 で追加.

shutil.get_archive_formats()

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

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

   * *zip*: ZIP file (if the "zlib" module or external "zip"
     executable is available).

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

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

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

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

   バージョン 2.7 で追加.

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

   Register an archiver for the format *name*. *function* is a
   callable that will be used to invoke the archiver.

   If given, *extra_args* is a sequence of "(name, value)" that will
   be used as extra keywords arguments when the archiver callable is
   used.

   *description* is used by "get_archive_formats()" which returns the
   list of archivers. Defaults to an empty list.

   バージョン 2.7 で追加.

shutil.unregister_archive_format(name)

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

   バージョン 2.7 で追加.


アーカイブ化の例
----------------

この例では、ユーザの ".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
