0

ディレクトリ A からディレクトリ B にファイルを再帰的にコピーする関数を作成します。コードは次のようになります。

import os
import shutil
import sys
from os.path import join, exists

def copy_file(src, dest):
    for path, dirs, files in os.walk(src, topdown=True):
        if len(dirs) > 0:
            for di in dirs:
                copy_file(join(path, di), join(dest,  di))

        if not exists(dest):
            os.makedirs(dest)
        for fi in files:
            shutil.copy(join(path, fi), dest)

私のテストでは、入力引数は次のようになります。

ソース = d:/dev

という名前のサブディレクトリが 1 つありpyます。また、pyという名前のサブディレクトリがありますtest

dest = d:/dev_bak

そのため、コードをテストすると、奇妙なことが起こりました。である私のdestディレクトリにはd:/dev_bak、3 つのサブディレクトリが作成されます。つまり: d:/dev_bak/py; d:/dev_bak/py/test; d:/dev_bak/test.

私の設計では、 の構造はdev_bakと同じになりますdev。では、どうしてこうなった!

4

2 に答える 2

2

これは、次のように簡単に診断できます

    print path, dirs, files

真下

for path, dirs, files in os.walk(src, topdown=True):

基本的に、2回再帰しています。

それ自体で、os.walkサブディレクトリに降ります。独自の関数を再帰的に呼び出すことで、二重降下しています。printそのステートメントからの出力例を次に示します。

>>> copy_file("c:\Intel", "c:\Intel-Bak")
c:\Intel ['ExtremeGraphics', 'ログ'] []
c:\Intel\ExtremeGraphics ['CUI'] []
c:\Intel\ExtremeGraphics\CUI ['リソース'] []
c:\Intel\ExtremeGraphics\CUI\Resource [] ['Intel\xae Graphics and Media Control Panel.lnk', 'Intel\xae HD Graphics.lnk']
c:\Intel\ExtremeGraphics\CUI\Resource [] ['Intel\xae Graphics and Media Control Panel.lnk', 'Intel\xae HD Graphics.lnk']
c:\Intel\ExtremeGraphics\CUI ['リソース'] []
c:\Intel\ExtremeGraphics\CUI\Resource [] ['Intel\xae Graphics and Media Control Panel.lnk', 'Intel\xae HD Graphics.lnk']
c:\Intel\ExtremeGraphics\CUI\Resource [] ['Intel\xae Graphics and Media Control Panel.lnk', 'Intel\xae HD Graphics.lnk']
c:\Intel\Logs [] ['IntelChipset.log', 'IntelControlCenter.log', 'IntelGFX.log', 'IntelGFXCoin.log']
c:\Intel\ExtremeGraphics ['CUI'] []
c:\Intel\ExtremeGraphics\CUI ['リソース'] []
c:\Intel\ExtremeGraphics\CUI\Resource [] ['Intel\xae Graphics and Media Control Panel.lnk', 'Intel\xae HD Graphics.lnk']
c:\Intel\ExtremeGraphics\CUI\Resource [] ['Intel\xae Graphics and Media Control Panel.lnk', 'Intel\xae HD Graphics.lnk']
c:\Intel\ExtremeGraphics\CUI ['リソース'] []
c:\Intel\ExtremeGraphics\CUI\Resource [] ['Intel\xae Graphics and Media Control Panel.lnk', 'Intel\xae HD Graphics.lnk']
c:\Intel\ExtremeGraphics\CUI\Resource [] ['Intel\xae Graphics and Media Control Panel.lnk', 'Intel\xae HD Graphics.lnk']
c:\Intel\Logs [] ['IntelChipset.log', 'IntelControlCenter.log', 'IntelGFX.log', 'IntelGFXCoin.log']

ご覧のとおり、ディレクトリは 2 回アクセスされます。

プログラムのロジックを修正して、各ディレクトリに一度だけアクセスするようにする必要がありますが、理論的には、既にアクセスしたディレクトリは無視できます。

visited = []
def copy_file(src, dest):
    for path, dirs, files in os.walk(src, topdown=True):
        if path not in visited:
            for di in dirs:
                print dest, di
                copy_file(join(path, di), join(dest,  di))
            if not exists(dest):
                os.makedirs(dest)
            for fi in files:
                shutil.copy(join(path, fi), dest)
            visited.append(path)
于 2012-04-11T17:00:19.627 に答える
0

shutilモジュールには、ディレクトリを再帰的にコピーする copytree 関数が既にあります独自の実装を提供する代わりに、それを使用したい場合があります。

于 2012-04-11T16:54:16.827 に答える