2016-08-10 19 views
10

Tôi muốn sao chép nhiều thư mục với cấu trúc giống nhau (thư mục con có cùng tên) nhưng nội dung khác nhau vào vị trí thứ ba và hợp nhất chúng. Đồng thời, tôi muốn bỏ qua một số phần mở rộng tập tin nhất định và không sao chép chúng.Sao chép và hợp nhất các thư mục, trừ các phần mở rộng nhất định


tôi thấy rằng nhiệm vụ đầu tiên một mình có thể dễ dàng xử lý bởi copy_tree() chức năng từ thư viện distutils.dir_util. Vấn đề ở đây là copy_tree() không thể bỏ qua tệp; nó chỉ đơn giản là bản sao tất cả mọi thứ ..

distutils.dir_util.copy_tree() - ví dụ

dirs_to_copy = [r'J:\Data\Folder_A', r'J:\Data\Folder_B'] 
destination_dir = r'J:\Data\DestinationFolder' 
for files in dirs_to_copy: 
    distutils.dir_util.copy_tree(files, destination_dir) 
    # succeeds in merging sub-directories but copies everything. 
    # Due to time constrains, this is not an option. 

Đối với nhiệm vụ thứ hai (sao chép với tùy chọn ngăn chặn các file) có các copytree() chức năng từ thư viện shutil lần này. Vấn đề với điều đó bây giờ là nó không thể hợp nhất các thư mục từ thư mục đích không phải tồn tại ..

shutil.copytree() - ví dụ

dirs_to_copy = [r'J:\Data\Folder_A', r'J:\Data\Folder_B'] 
destination_dir = r'J:\Data\DestinationFolder' 
for files in dirs_to_copy: 
    shutil.copytree(files, destination_dir, ignore=shutil.ignore_patterns("*.abc")) 
    # successfully ignores files with "abc" extensions but fails 
    # at the second iteration since "Destination" folder exists.. 

Có cái gì đó cung cấp tốt nhất của cả hai thế giới hay tôi phải tự viết mã này?

+0

Cách tinh chỉnh [ví dụ copytree tắt] (https://docs.python.org/2/library/shutil.html#copytree-example) để bỏ qua các thư mục trùng lặp bằng cách bắt lỗi từ ' makedirs'? –

+0

@PeterBrittain Nhưng nếu tôi làm điều đó, nó sẽ bỏ qua các thư mục hoàn toàn đúng không? Và, tôi cần nội dung của họ. –

+0

Không, không. Nó sẽ cố gắng làm cho tất cả các thư mục, nhấn một ngoại lệ (mà bạn nuốt với một thử mới ... trừ hander xung quanh một dòng) và sau đó chuyển sang thư mục đi bộ (sao chép các tập tin hoặc đệ quy khi cần thiết). –

Trả lời

3

Như PeterBrittain gợi ý, viết phiên bản riêng của tôi về shutil.copytree() được con đường để đi. Dưới đây là mã. Lưu ý rằng sự khác biệt duy nhất là gói os.makedirs() trong khối if.

from shutil import copy2, copystat, Error, ignore_patterns 
import os 


def copytree_multi(src, dst, symlinks=False, ignore=None): 
    names = os.listdir(src) 
    if ignore is not None: 
     ignored_names = ignore(src, names) 
    else: 
     ignored_names = set() 

    # -------- E D I T -------- 
    # os.path.isdir(dst) 
    if not os.path.isdir(dst): 
     os.makedirs(dst) 
    # -------- E D I T -------- 

    errors = [] 
    for name in names: 
     if name in ignored_names: 
      continue 
     srcname = os.path.join(src, name) 
     dstname = os.path.join(dst, name) 
     try: 
      if symlinks and os.path.islink(srcname): 
       linkto = os.readlink(srcname) 
       os.symlink(linkto, dstname) 
      elif os.path.isdir(srcname): 
       copytree_multi(srcname, dstname, symlinks, ignore) 
      else: 
       copy2(srcname, dstname) 
     except (IOError, os.error) as why: 
      errors.append((srcname, dstname, str(why))) 
     except Error as err: 
      errors.extend(err.args[0]) 
    try: 
     copystat(src, dst) 
    except WindowsError: 
     pass 
    except OSError as why: 
     errors.extend((src, dst, str(why))) 
    if errors: 
     raise Error(errors) 
0

nếu bạn muốn sử dụng trực tiếp, đây là bản vá nóng dành cho os.makedirs để bỏ qua lỗi.

import os 
os_makedirs = os.makedirs 
def safe_makedirs(name, mode=0777): 
    if not os.path.exists(name): 
     os_makedirs(name, mode) 
os.makedirs = safe_makedirs 

import shutil 

dirs_to_copy = [r'J:\Data\Folder_A', r'J:\Data\Folder_B'] 
destination_dir = r'J:\Data\DestinationFolder' 
if os.path.exists(destination_dir): 
    shutil.rmtree(destination_dir) 
for files in dirs_to_copy: 
    shutil.copytree(files, destination_dir, ignore=shutil.ignore_patterns("*.abc")) code here 
+0

Nhưng khi thực hiện 'shutil.rmtree (destination_dir)' tôi sẽ xóa nội dung của nó quá sẽ đến từ một thư mục sẽ không được sao chép lại. Cuối cùng tôi sẽ kết thúc với một bản sao của thư mục cuối cùng trong danh sách 'dirs_to_copy' và mọi thứ khác sẽ được sao chép và sau đó bị xóa. –

Các vấn đề liên quan