파이썬을 사용하여 파일의 전체 디렉토리를 기존 디렉토리에 어떻게 복사합니까?
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")
이 비슷한 질문을보십시오.
위 함수가 항상 소스에서 대상으로 파일을 복사하려고하는 함수에 대한 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가 이미 존재 하면 실패하지 않습니다
docs는 대상 디렉토리가 존재 하지 않아야 함을 명시 적으로 나타냅니다 .
로 이름이 지정된 대상 디렉토리가
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의 주석 처리를 제거하여 이동 기능으로 만드십시오.
파이썬이 시스템 명령을 호출하는 것이 가장 빠르고 간단한 방법이라고 가정합니다 ...
예..
import os
cmd = '<command line call>'
os.system(cmd)
타르와 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 인 경우 부울 입니다. dst
목록에없는 한 기존 파일보다 수정 된 날짜가있는 파일 만 복사합니다 forceupdate
.
ignore
및 forceupdate
파일 이름 또는 폴더의 목록을 기대 /는 파일 이름 을 기준으로 src
유닉스 스타일과 유사한 와일드 카드에 동의하고 glob
또는 fnmatch
.
이 함수는 복사 된 파일 목록을 반환합니다 (또는 dryrun
True 인 경우 복사 됨 ).
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
.
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")
다음은 pathlib.Path
입력 이 필요한 버전입니다 .
# Recusively copies the content of the directory src to the directory dst.
# If dst doesn't exist, it is created, together with all missing parent directories.
# If a file from src already exists in dst, the file in dst is overwritten.
# Files already existing in dst which don't exist in src are preserved.
# Symlinks inside src are copied as symlinks, they are not resolved before copying.
#
def copy_dir(src, dst):
dst.mkdir(parents=True, exist_ok=True)
for item in os.listdir(src):
s = src / item
d = dst / item
if s.is_dir():
copy_dir(s, d)
else:
shutil.copy2(str(s), str(d))
Note that this function requires Python 3.6, which is the first version of Python where os.listdir()
supports path-like objects as input. If you need to support earlier versions of Python, you can replace listdir(src)
by listdir(str(src))
.
'IT' 카테고리의 다른 글
Java 바이트 배열에서 문자열로 바이트 배열로 (0) | 2020.05.23 |
---|---|
파이썬에서 하나의 목록을 다른 목록에 삽입하는 구문은 무엇입니까? (0) | 2020.05.23 |
Node.js 및 .Net 성능 (0) | 2020.05.23 |
VS2015 Community Edition을 오프라인으로 설치하는 방법 (0) | 2020.05.23 |
O (1)의 고유 한 (반복되지 않는) 난수? (0) | 2020.05.23 |