web-dev-qa-db-ja.com

Python-ファイルとフォルダーの移動と上書き

ファイルとフォルダーが含まれるディレクトリ「Dst Directory」と、ファイルとフォルダーが含まれる「srcディレクトリ」があります。私がやりたいのは、「src Directory」の内容を「Dst Directory」に移動し、同じ名前で存在するファイルを上書きすることです。たとえば、「Src Directory\file.txt」を「Dst Directory \」に移動して、既存のfile.txtを上書きする必要があります。同じことが一部のフォルダーに適用され、フォルダーを移動し、内容を「dstディレクトリー」の同じフォルダーにマージします

現在、shutil.moveを使用してsrcの内容をdstに移動していますが、ファイルが既に存在し、フォルダーをマージしない場合は実行しません。既存のフォルダー内にフォルダーを配置するだけです。

更新:物事を少し明確にするため。私がしているのは、アーカイブをDstディレクトリに解凍し、Srcディレクトリの内容をそこに移動して、zipアーカイブ内のファイルを効果的に更新することです。これは、新しいファイルまたはファイルの新しいバージョンなどを追加するために繰り返されます。そのため、上書きしてマージする必要があります。

解決済み:distutils.dir_util.copy_tree(src、dst)を使用して問題を解決しました。これにより、フォルダーとファイルがsrcディレクトリーからdstディレクトリーにコピーされ、必要に応じて上書き/マージされます。それが一部の人々に役立つことを願っています!

それが理にかなっていることを願っています、ありがとう!

63
Artharos

代わりにcopy()を使用します。これにより、宛先ファイルが上書きされます。その後、最初のツリーを削除したい場合は、繰り返し処理が完了したら、rmtree()個別に削除します。

http://docs.python.org/library/shutil.html#shutil.copy

http://docs.python.org/library/shutil.html#shutil.rmtree

更新:

ソースツリーに対してos.walk()を実行します。各ディレクトリについて、宛先側に存在するかどうかを確認し、欠落している場合はos.makedirs()各ファイルに対して、単にshutil.copy()とファイルが適切に作成または上書きされます。

45
Brandon Rhodes

これは、ソースディレクトリを通過し、宛先ディレクトリに存在しないディレクトリを作成し、ソースから宛先ディレクトリにファイルを移動します。

import os
import shutil

root_src_dir = 'Src Directory\\'
root_dst_dir = 'Dst Directory\\'

for src_dir, dirs, files in os.walk(root_src_dir):
    dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
    if not os.path.exists(dst_dir):
        os.makedirs(dst_dir)
    for file_ in files:
        src_file = os.path.join(src_dir, file_)
        dst_file = os.path.join(dst_dir, file_)
        if os.path.exists(dst_file):
            # in case of the src and dst are the same file
            if os.path.samefile(src_file, dst_file):
                continue
            os.remove(dst_file)
        shutil.move(src_file, dst_dir)

既存のファイルは、対応するソースファイルに置き換えられる前に(os.removeを介して)最初に削除されます。宛先にすでに存在し、ソースには存在しないファイルまたはディレクトリは変更されません。

52
Ray Vega

上記のどれも私には役に立たなかったので、自分で再帰関数を作成しました。関数copyTree(dir1、dir2)を呼び出して、ディレクトリをマージします。マルチプラットフォームのLinuxおよびWindowsで実行します。

def forceMergeFlatDir(srcDir, dstDir):
    if not os.path.exists(dstDir):
        os.makedirs(dstDir)
    for item in os.listdir(srcDir):
        srcFile = os.path.join(srcDir, item)
        dstFile = os.path.join(dstDir, item)
        forceCopyFile(srcFile, dstFile)

def forceCopyFile (sfile, dfile):
    if os.path.isfile(sfile):
        shutil.copy2(sfile, dfile)

def isAFlatDir(sDir):
    for item in os.listdir(sDir):
        sItem = os.path.join(sDir, item)
        if os.path.isdir(sItem):
            return False
    return True


def copyTree(src, dst):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isfile(s):
            if not os.path.exists(dst):
                os.makedirs(dst)
            forceCopyFile(s,d)
        if os.path.isdir(s):
            isRecursive = not isAFlatDir(s)
            if isRecursive:
                copyTree(s, d)
            else:
                forceMergeFlatDir(s, d)
6
ALLOY

読み取り専用フラグでファイルを上書きする必要がある場合は、これを使用します。

def copyDirTree(root_src_dir,root_dst_dir):
"""
Copy directory tree. Overwrites also read only files.
:param root_src_dir: source directory
:param root_dst_dir:  destination directory
"""
for src_dir, dirs, files in os.walk(root_src_dir):
    dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
    if not os.path.exists(dst_dir):
        os.makedirs(dst_dir)
    for file_ in files:
        src_file = os.path.join(src_dir, file_)
        dst_file = os.path.join(dst_dir, file_)
        if os.path.exists(dst_file):
            try:
                os.remove(dst_file)
            except PermissionError as exc:
                os.chmod(dst_file, stat.S_IWUSR)
                os.remove(dst_file)

        shutil.copy(src_file, dst_dir)
4
Vit Bernatik

既存のファイルを削除するには、 os.remove をご覧ください。

1
phimuemue

同様の問題がありました。ファイルとフォルダー構造を移動し、既存のファイルを上書きしたいのですが、目的のフォルダー構造にあるものは削除しませんでした。

os.walk()を使用して、関数を再帰的に呼び出し、上書きしたいファイルと存在しないフォルダーでshutil.move()を使用して解決しました。

shutil.move()と同様に機能しますが、既存のファイルは上書きされるだけで削除されないという利点があります。

import os
import shutil

def moverecursively(source_folder, destination_folder):
    basename = os.path.basename(source_folder)
    dest_dir = os.path.join(destination_folder, basename)
    if not os.path.exists(dest_dir):
        shutil.move(source_folder, destination_folder)
    else:
        dst_path = os.path.join(destination_folder, basename)
        for root, dirs, files in os.walk(source_folder):
            for item in files:
                src_path = os.path.join(root, item)
                if os.path.exists(dst_file):
                    os.remove(dst_file)
                shutil.move(src_path, dst_path)
            for item in dirs:
                src_path = os.path.join(root, item)
                moverecursively(src_path, dst_path)
0
the