Python을 사용하여 전체 파일의 전체 디렉토리를 기존 디렉토리에 복사하려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/1868714

  •  18-09-2019
  •  | 
  •  

문제

명명 된 디렉토리가 포함 된 디렉토리에서 다음 코드를 실행합니다. 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() 각 파일을 복사합니다 baz ~ 안으로 foo? (내가 이미 'bar'의 내용을 'foo'로 복사 한 후 shutil.copytree()?) 아니면 더 쉬운/더 나은 방법이 있습니까?

도움이 되었습니까?

해결책

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

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)

표준 카피 트리와 완전히 일치하지는 않습니다.

  • 존경하지 않습니다 symlinks 그리고 ignore 루트 디렉토리의 매개 변수 src 나무;
  • 그것은 일어나지 않습니다 shutil.Error 루트 레벨의 오류 src;
  • 하위 트리를 복사하는 동안 오류가 발생하면 shutil.Error 다른 하위 트리를 복사하려고 시도하고 단일 결합을 올리는 대신 해당 하위 트리의 경우 shutil.Error.

다른 팁

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

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

이 비슷한 질문을 참조하십시오.

디렉토리 내용을 Python이있는 디렉토리로 복사하십시오

위의 함수가 항상 소스에서 대상으로 파일을 복사하려는 기능에 대한 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)

위의 구현에서

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

스콘 빌드와 함께 위의 기능을 사용하고 있습니다. 컴파일 할 때마다 전체 파일 세트를 복사 할 필요가 없지만 수정 된 파일 만 복사 할 필요가 없습니다.

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, 와 함께 Symlinks 그리고 무시하다 매개 변수
  • 존재하지 않는 경우 디렉토리 대상 구조를 만듭니다
  • 경우 실패하지 않습니다 DST 이미 존재 함

문서는 대상 디렉토리가해야한다고 명시 적으로 명시합니다 ~ 아니다 존재하다:

대상 디렉토리 dst, 아직 존재해서는 안됩니다. 입자 디렉토리가 누락 될뿐만 아니라 만들어집니다.

당신의 최선의 방법은 os.walk 두 번째와 모든 결과 디렉토리, copy2 디렉토리 및 파일 및 추가 작업 copystat 디렉토리 용. 결국 그것은 정확히 무엇입니다 copytree 문서에 설명 된대로. 또는 당신은 할 수 있습니다 copy 그리고 copystat 각 디렉토리/파일 및 os.listdir 대신에 os.walk.

수정할 수 있습니다 shutil 그리고 효과를 얻으십시오 (내 버전에서 shutil 이것은 줄에 있습니다 315)

변화

os.makedirs(dst)

에게

os.makedirs(dst,exist_ok=True)

이것은 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를 움직이지 않기 위해 rmtree를 사용하십시오.

가장 빠르고 간단한 방법은 파이썬이 시스템 명령을 호출하는 것입니다 ...

예시..

import os
cmd = '<command line call>'
os.system(cmd)

Tar and Gzip 디렉토리를 위로 올리십시오 .... 원하는 장소에서 디렉토리를 압축하고 untar.

야아?

다음은 동일한 작업의 내 버전입니다.

import os, glob, shutil

def make_dir(path):
    if not os.path.isdir(path):
        os.mkdir(path)


def copy_dir(source_item, destination_item):
    if os.path.isdir(source_item):
        make_dir(destination_item)
        sub_items = glob.glob(source_item + '/*')
        for sub_item in sub_items:
            copy_dir(sub_item, destination_item + '/' + sub_item.split('/')[-1])
    else:
        shutil.copy(source_item, destination_item)

다음은이 스레드에서 영감을 얻은 버전입니다. distutils.file_util.copy_file.

updateonly true 인 경우 bool입니다. 기존 파일보다 새로 수정 된 날짜가있는 파일 만 복사합니다. dst 나열되지 않는 한 forceupdate 상관없이 복사합니다.

ignore 그리고 forceupdate 파일 이름 또는 폴더/파일 이름 목록을 기대하십시오 관련 src 그리고 유사한 유닉스 스타일 와일드 카드를 받아들입니다 glob 또는 fnmatch.

함수는 복사 된 파일 목록을 반환합니다 (또는 dryrun 사실이면).

import os
import shutil
import fnmatch
import stat
import itertools

def copyToDir(src, dst, updateonly=True, symlinks=True, ignore=None, forceupdate=None, dryrun=False):

    def copySymLink(srclink, destlink):
        if os.path.lexists(destlink):
            os.remove(destlink)
        os.symlink(os.readlink(srclink), destlink)
        try:
            st = os.lstat(srclink)
            mode = stat.S_IMODE(st.st_mode)
            os.lchmod(destlink, mode)
        except OSError:
            pass  # lchmod not available
    fc = []
    if not os.path.exists(dst) and not dryrun:
        os.makedirs(dst)
        shutil.copystat(src, dst)
    if ignore is not None:
        ignorepatterns = [os.path.join(src, *x.split('/')) for x in ignore]
    else:
        ignorepatterns = []
    if forceupdate is not None:
        forceupdatepatterns = [os.path.join(src, *x.split('/')) for x in forceupdate]
    else:
        forceupdatepatterns = []
    srclen = len(src)
    for root, dirs, files in os.walk(src):
        fullsrcfiles = [os.path.join(root, x) for x in files]
        t = root[srclen+1:]
        dstroot = os.path.join(dst, t)
        fulldstfiles = [os.path.join(dstroot, x) for x in files]
        excludefiles = list(itertools.chain.from_iterable([fnmatch.filter(fullsrcfiles, pattern) for pattern in ignorepatterns]))
        forceupdatefiles = list(itertools.chain.from_iterable([fnmatch.filter(fullsrcfiles, pattern) for pattern in forceupdatepatterns]))
        for directory in dirs:
            fullsrcdir = os.path.join(src, directory)
            fulldstdir = os.path.join(dstroot, directory)
            if os.path.islink(fullsrcdir):
                if symlinks and dryrun is False:
                    copySymLink(fullsrcdir, fulldstdir)
            else:
                if not os.path.exists(directory) and dryrun is False:
                    os.makedirs(os.path.join(dst, dir))
                    shutil.copystat(src, dst)
        for s,d in zip(fullsrcfiles, fulldstfiles):
            if s not in excludefiles:
                if updateonly:
                    go = False
                    if os.path.isfile(d):
                        srcdate = os.stat(s).st_mtime
                        dstdate = os.stat(d).st_mtime
                        if srcdate > dstdate:
                            go = True
                    else:
                        go = True
                    if s in forceupdatefiles:
                        go = True
                    if go is True:
                        fc.append(d)
                        if not dryrun:
                            if os.path.islink(s) and symlinks is True:
                                copySymLink(s, d)
                            else:
                                shutil.copy2(s, d)
                else:
                    fc.append(d)
                    if not dryrun:
                        if os.path.islink(s) and symlinks is True:
                            copySymLink(s, d)
                        else:
                            shutil.copy2(s, d)
    return fc

이전 솔루션에는 몇 가지 문제가 있습니다 src 덮어 쓸 수 있습니다 dst 알림이나 예외없이.

나는 a를 추가한다 predict_error 사본 전에 오류를 예측하는 메소드.copytree 주로 Cyrille Pontvieux 버전을 기반으로합니다.

사용 predict_error 실행할 때 예외가 서로 제기되는 것을보고 싶지 않다면 처음에는 모든 오류를 예측하는 것이 가장 좋습니다. copytree 모든 오류를 수정할 때까지.

def predict_error(src, dst):  
    if os.path.exists(dst):
        src_isdir = os.path.isdir(src)
        dst_isdir = os.path.isdir(dst)
        if src_isdir and dst_isdir:
            pass
        elif src_isdir and not dst_isdir:
            yield {dst:'src is dir but dst is file.'}
        elif not src_isdir and dst_isdir:
            yield {dst:'src is file but dst is dir.'}
        else:
            yield {dst:'already exists a file with same name in dst'}

    if os.path.isdir(src):
        for item in os.listdir(src):
            s = os.path.join(src, item)
            d = os.path.join(dst, item)
            for e in predict_error(s, d):
                yield e


def copytree(src, dst, symlinks=False, ignore=None, overwrite=False):
    '''
    would overwrite if src and dst are both file
    but would not use folder overwrite file, or viceverse
    '''
    if not overwrite:
        errors = list(predict_error(src, dst))
        if errors:
            raise Exception('copy would overwrite some file, error detail:%s' % errors)

    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:
            if not overwrite:
                if os.path.exists(d):
                    continue
            shutil.copy2(s, d)

여기에 문제가 있습니다. 원래 기능을 유지하기 위해 CopyTree의 소스 코드를 수정했지만 이제 디렉토리가 이미 존재할 때 오류가 발생하지 않습니다. 또한 기존 파일을 덮어 쓰지 않고 내 응용 프로그램에 중요했기 때문에 모든 파일을 덮어 쓰지 않고 두 개의 사본을 수정했습니다.

import shutil
import os


def _copytree(src, dst, symlinks=False, ignore=None):
    """
    This is an improved version of shutil.copytree which allows writing to
    existing folders and does not overwrite existing files but instead appends
    a ~1 to the file name and adds it to the destination path.
    """

    names = os.listdir(src)
    if ignore is not None:
        ignored_names = ignore(src, names)
    else:
        ignored_names = set()

    if not os.path.exists(dst):
        os.makedirs(dst)
        shutil.copystat(src, dst)
    errors = []
    for name in names:
        if name in ignored_names:
            continue
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        i = 1
        while os.path.exists(dstname) and not os.path.isdir(dstname):
            parts = name.split('.')
            file_name = ''
            file_extension = parts[-1]
            # make a new file name inserting ~1 between name and extension
            for j in range(len(parts)-1):
                file_name += parts[j]
                if j < len(parts)-2:
                    file_name += '.'
            suffix = file_name + '~' + str(i) + '.' + file_extension
            dstname = os.path.join(dst, suffix)
            i+=1
        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:
                shutil.copy2(srcname, dstname)
        except (IOError, os.error) as why:
            errors.append((srcname, dstname, str(why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except BaseException as err:
            errors.extend(err.args[0])
    try:
        shutil.copystat(src, dst)
    except WindowsError:
        # can't copy file access times on Windows
        pass
    except OSError as why:
        errors.extend((src, dst, str(why)))
    if errors:
        raise BaseException(errors)

이 시도:

import os,shutil

def copydir(src, dst):
  h = os.getcwd()
  src = r"{}".format(src)
  if not os.path.isdir(dst):
     print("\n[!] No Such directory: ["+dst+"] !!!")
     exit(1)

  if not os.path.isdir(src):
     print("\n[!] No Such directory: ["+src+"] !!!")
     exit(1)
  if "\\" in src:
     c = "\\"
     tsrc = src.split("\\")[-1:][0]
  else:
    c = "/"
    tsrc = src.split("/")[-1:][0]

  os.chdir(dst)
  if os.path.isdir(tsrc):
    print("\n[!] The Directory Is already exists !!!")
    exit(1)
  try:
    os.mkdir(tsrc)
  except WindowsError:
    print("\n[!] Error: In[ {} ]\nPlease Check Your Dirctory Path !!!".format(src))
    exit(1)
  os.chdir(h)
  files = []
  for i in os.listdir(src):
    files.append(src+c+i)
  if len(files) > 0:
    for i in files:
        if not os.path.isdir(i):
            shutil.copy2(i, dst+c+tsrc)

  print("\n[*] Done ! :)")

copydir("c:\folder1", "c:\folder2")
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top