[python] Python을 사용하여 파일의 전체 디렉토리를 기존 디렉토리에 복사하는 방법은 무엇입니까?

bar하나 이상의 파일 을 포함하는 디렉토리 와 하나 이상의 파일 을 포함하는 디렉토리를 포함하는 디렉토리에서 다음 코드를 실행하십시오 baz. 라는 디렉토리가 없는지 확인하십시오 foo.

import shutil
shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo')

다음과 같이 실패합니다.

$ python copytree_test.py 
Traceback (most recent call last):
  File "copytree_test.py", line 5, in <module>
    shutil.copytree('baz', 'foo')
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/shutil.py", line 110, in copytree
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/os.py", line 172, in makedirs
OSError: [Errno 17] File exists: 'foo'

나는 마치 타이핑 한 것과 같은 방식으로 작동하기를 원합니다.

$ mkdir foo
$ cp bar/* foo/
$ cp baz/* foo/

내가 사용해야하는 shutil.copy()각각의 파일을 복사 bazfoo? (이미 ‘bar’의 내용을 ‘ shutil.copytree()? ‘를 사용하여 ‘foo’에 복사 한 후 ) 더 쉬운 방법이 있습니까?



답변

이 표준의 한계는 shutil.copytree자의적이고 성가신 것 같습니다. 해결 방법 :

import os, shutil
def copytree(src, dst, symlinks=False, ignore=None):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isdir(s):
            shutil.copytree(s, d, symlinks, ignore)
        else:
            shutil.copy2(s, d)

표준과 완전히 일치하지는 않습니다 copytree.

  • 트리 의 루트 디렉토리에 대한 매개 변수 symlinksignore매개 변수를 존중하지 않습니다 src.
  • shutil.Error루트 수준에서 오류가 발생 하지 않습니다 src.
  • 서브 트리 복사 중 오류가 발생하면 shutil.Error다른 서브 트리를 복사하려고 시도하고 단일 결합을 발생시키는 대신 해당 서브 트리에 대해 발생 shutil.Error합니다.

답변

표준 라이브러리의 일부인 솔루션은 다음과 같습니다.

from distutils.dir_util import copy_tree
copy_tree("/a/b/c", "/x/y/z")

이 비슷한 질문을보십시오.

파이썬으로 디렉토리에 디렉토리 내용 복사


답변

위 함수가 항상 소스에서 대상으로 파일을 복사하려고하는 함수에 대한 atzz의 대답이 약간 개선되었습니다.

def copytree(src, dst, symlinks=False, ignore=None):
    if not os.path.exists(dst):
        os.makedirs(dst)
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isdir(s):
            copytree(s, d, symlinks, ignore)
        else:
            if not os.path.exists(d) or os.stat(s).st_mtime - os.stat(d).st_mtime > 1:
                shutil.copy2(s, d)

위의 구현에서

  • 존재하지 않는 경우 출력 디렉토리 작성
  • 내 자신의 메소드를 재귀 적으로 호출하여 복사 디렉토리 수행
  • 실제로 파일을 복사 할 때 파일이 수정되었는지 확인한 다음 복사해야합니다.

scons 빌드와 함께 위의 기능을 사용하고 있습니다. 컴파일 할 때마다 전체 파일 세트를 복사 할 필요는 없지만 수정 된 파일 만 복사하면 도움이되었습니다.


답변

atzz와 Mital Vora에서 영감을 얻은 병합 :

#!/usr/bin/python
import os
import shutil
import stat
def copytree(src, dst, symlinks = False, ignore = None):
  if not os.path.exists(dst):
    os.makedirs(dst)
    shutil.copystat(src, dst)
  lst = os.listdir(src)
  if ignore:
    excl = ignore(src, lst)
    lst = [x for x in lst if x not in excl]
  for item in lst:
    s = os.path.join(src, item)
    d = os.path.join(dst, item)
    if symlinks and os.path.islink(s):
      if os.path.lexists(d):
        os.remove(d)
      os.symlink(os.readlink(s), d)
      try:
        st = os.lstat(s)
        mode = stat.S_IMODE(st.st_mode)
        os.lchmod(d, mode)
      except:
        pass # lchmod not available
    elif os.path.isdir(s):
      copytree(s, d, symlinks, ignore)
    else:
      shutil.copy2(s, d)
  • 동일 행동 shutil.copytree 와, 심볼릭 링크무시 매개 변수를
  • 존재하지 않는 경우 디렉토리 대상 구조 작성
  • dst가 이미 존재 하면 실패하지 않습니다

답변

파이썬 3.8은 다음과 같은 dirs_exist_ok주장소개 했습니다 shutil.copytree.

src 를 루트로하는 전체 디렉토리 트리를 dst 라는 디렉토리에 재귀 적으로 복사 하고 대상 디렉토리를 리턴하십시오. dirs_exist_okdst 또는 누락 된 상위 디렉토리가 이미 존재하는 경우 예외를 발생 시킬지 여부를 나타냅니다 .

따라서 Python 3.8 이상에서는 다음과 같이 작동합니다.

import shutil

shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo', dirs_exist_ok=True)


답변

docs는 대상 디렉토리가 존재 하지 않아야 함을 명시 적으로 나타냅니다 .

로 이름이 지정된 대상 디렉토리가 dst아직 존재하지 않아야합니다. 상위 디렉토리가 누락 될뿐만 아니라 작성됩니다.

가장 좋은 방법은 os.walk두 번째 및 모든 후속 디렉토리, copy2디렉토리 및 파일에 대한 것이며 copystat디렉토리에 추가 작업을 수행하는 것 입니다. 결국 그것은 copytree문서에 설명 된 것과 정확히 일치합니다 . 또는 당신은 할 수 copycopystat각 디렉토리 / 파일 os.listdir대신 os.walk.


답변

이것은 atzz가 제공 한 원래의 최고의 답변에서 영감을 얻었습니다. 바로 파일 / 폴더 논리 바꾸기를 추가했습니다. 따라서 실제로 병합되지 않지만 기존 파일 / 폴더를 삭제하고 새 파일 / 폴더를 복사합니다.

import shutil
import os
def copytree(src, dst, symlinks=False, ignore=None):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.exists(d):
            try:
                shutil.rmtree(d)
            except Exception as e:
                print e
                os.unlink(d)
        if os.path.isdir(s):
            shutil.copytree(s, d, symlinks, ignore)
        else:
            shutil.copy2(s, d)
    #shutil.rmtree(src)

rmtree의 주석 처리를 제거하여 이동 기능으로 만드십시오.