2011-09-14 42 views
51

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

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

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

解決済み:私はdistutils.dir_util.copy_tree(src、dst)を使用して問題を解決しました。 srcディレクトリからdstディレクトリにファイルをコピーし、必要な場所を上書き/マージします。いくつかの人々に役立つことを願っています!

希望は意味がある、 ありがとう!

+0

注[ 'distutils.dir_util.copy_tree'](そのhttps://docs.python.org/dev /distutils/apiref.html#distutils.dir_util.copy_tree)は特別なファイルをコピーできません。 [named pipes](https://en.wikipedia.org/wiki/Named_pipe)( 'distutils.errors.DistutilsFileError'を投げます)。 –

答えて

35

代わりに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()となり、ファイルは作成または上書きされます。どちらか適切な方。

+0

copy()しかし、フォルダをコピーすることはできますか? – Artharos

+0

いいえ、各ファイルの 'move()'も目的のディレクトリを作成しませんので、あなたのコードは存在しなかった目的地のフォルダに 'os.makedirs()'をすでに行っていると仮定しました。ああ!私は今、あなたが理解していると思う - あなたは一度に*全体の木の上で '移動()'をしていたのですか?ゴッチャ。私の答えが更新されます。 –

+0

更新していただきありがとうございます。その問題は、コピーするファイルが常に変更されている(新しいファイルが追加されたなど)ため、移動するために新しいファイルを追加するたびにコードを更新する必要があります。とにかく、distutils.dir_util.copy_tree(src、dst)で管理しました。これは、フォルダとファイルをコピーし、助けを借りて、助けてくれます。 – Artharos

1

os.removeをご覧になり、既存のファイルを削除してください。

+0

問題は、フォルダに追加したいファイルが変更される(新しいものが追加され、古いものが更新される)ので、削除する対象のリストを設定できないためです。 – Artharos

44

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

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): 
      os.remove(dst_file) 
     shutil.move(src_file, dst_dir) 

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

+3

それはいいです、ありがとう!私はそれがBrandon Craig Rhodesが話していたものだと思うが、スニペットを提供してくれてありがとう!残念ながら、2つの正解を持つことはできません^^ – Artharos

+1

No prob。 :)うまくいけば、私たちの答えのそれぞれが役に立ちます。 –

+2

そして、それらをコピーするには、 "shutil.move"を "shutil.copy"に置き換えるのが簡単です。 – Karoh

6

上記のどれも私のために働いていないので、自分の再帰関数を書きました。ディレクトリをマージするには、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) 
+0

これは、動作する唯一のものです – user1447414

+0

他の回答を使用しているときにシナリオはうまくいかなかったのですか? – cgmb

+0

注目すべきことに、srcにdstのディレクトリと同じ名前のファイルがある場合、このソリューションはその名前を共有するディレクトリの中にファイルを置きますが、[Ray Vegaの解答](http://stackoverflow.com/a/ 7420617/331041)は 'OSError:[Errno 21] is a directory'を送出します。 – cgmb

0

私にも同様の問題がありました。ファイルとフォルダ構造を移動して既存のファイルを上書きしたいが、コピー先のフォルダ構造にあるものは削除しない。

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) 
3

あなたもこの読み取り専用フラグを使用してファイルを上書きする必要がある場合:

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) 
関連する問題