web-dev-qa-db-ja.com

pythonでディレクトリを再帰的にコピーし、すべてを上書きする方法は?

/home/myUser/dir1/とそのすべてのコンテンツ(およびそのコンテンツなど)をpythonの/home/myuser/dir2/にコピーしようとしています。さらに、コピーでdir2/のすべてを上書きする必要があります。

distutils.dir_util.copy_treeのようなlooksは、このジョブに適したツールかもしれませんが、そのような単純なタスクに使用するのがより簡単/明白なものがあるかどうかはわかりません。

適切なツールである場合、どのように使用すればよいですか? docs によると、8つのパラメーターが必要です。 8つすべてをsrcdstおよびupdateだけで渡す必要がありますか。

より良いものがそこにある場合、誰かが私に例を挙げて正しい方向に私を向けることができますか?前もって感謝します!

57
IAmYourFaja

使用できます distutils.dir_util.copy_tree 。うまく機能し、すべての引数を渡す必要はありません。srcdstのみが必須です。

ただし、あなたの場合、次のような同様のツールを使用することはできませんshutil.copytree動作が異なるため。宛先ディレクトリが存在してはならないため、この関数を使用してコンテンツを上書きすることはできません。

質問のコメントで提案されているようにcpツールを使用したい場合、os.systemの ドキュメントにあるように、subprocessモジュールを使用することが現在推奨される新しいプロセスの生成方法であることに注意してください関数

54
Vicent

shutil パッケージ、特に rmtree および copytree をご覧ください。 os.paths.exists(<path>)でファイル/パスが存在するかどうかを確認できます。

_import shutil
import os

def copy_and_overwrite(from_path, to_path):
    if os.path.exists(to_path):
        shutil.rmtree(to_path)
    shutil.copytree(from_path, to_path)
_

既に存在する場合、Vincentはcopytreeが機能していないことについて正しかった。したがって、distutilsの方が優れたバージョンです。以下は_shutil.copytree_の修正バージョンです。 if-else-constructの後ろにある最初のos.makedirs()を除いて、基本的に1-1でコピーされます。

_import os
from shutil import *
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()

    if not os.path.isdir(dst): # This one line does the trick
        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:
                # Will raise a SpecialFileError for unsupported file types
                copy2(srcname, dstname)
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except Error, err:
            errors.extend(err.args[0])
        except EnvironmentError, why:
            errors.append((srcname, dstname, str(why)))
    try:
        copystat(src, dst)
    except OSError, why:
        if WindowsError is not None and isinstance(why, WindowsError):
            # Copying file access times may fail on Windows
            pass
        else:
            errors.extend((src, dst, str(why)))
    if errors:
        raise Error, errors
_
31
Michael

宛先をソースで再帰的に上書きし、必要なディレクトリを作成する簡単なソリューションを次に示します。これはシンボリックリンクを処理しませんが、単純な拡張機能です(上記の@Michaelによる回答を参照)。

def recursive_overwrite(src, dest, ignore=None):
    if os.path.isdir(src):
        if not os.path.isdir(dest):
            os.makedirs(dest)
        files = os.listdir(src)
        if ignore is not None:
            ignored = ignore(src, files)
        else:
            ignored = set()
        for f in files:
            if f not in ignored:
                recursive_overwrite(os.path.join(src, f), 
                                    os.path.join(dest, f), 
                                    ignore)
    else:
        shutil.copyfile(src, dest)
20
mgrant