如何在Python中复制文件?


当前回答

这是一个利用“shutil.copyfileobj”的答案,它非常高效。我在不久前创建的一个工具中使用了它。我最初没有写这篇文章,但我稍微修改了一下。

def copyFile(src, dst, buffer_size=10485760, perserveFileDate=True):
    '''
    @param src:    Source File
    @param dst:    Destination File (not file path)
    @param buffer_size:    Buffer size to use during copy
    @param perserveFileDate:    Preserve the original file date
    '''
    #    Check to make sure destination directory exists. If it doesn't create the directory
    dstParent, dstFileName = os.path.split(dst)
    if(not(os.path.exists(dstParent))):
        os.makedirs(dstParent)

    # Optimize the buffer for small files
    buffer_size = min(buffer_size,os.path.getsize(src))
    if(buffer_size == 0):
        buffer_size = 1024

    if shutil._samefile(src, dst):
        raise shutil.Error("`%s` and `%s` are the same file" % (src, dst))
    for fn in [src, dst]:
        try:
            st = os.stat(fn)
        except OSError:
            # File most likely does not exist
            pass
        else:
            # XXX What about other special files? (sockets, devices...)
            if shutil.stat.S_ISFIFO(st.st_mode):
                raise shutil.SpecialFileError("`%s` is a named pipe" % fn)
    with open(src, 'rb') as fsrc:
        with open(dst, 'wb') as fdst:
            shutil.copyfileobj(fsrc, fdst, buffer_size)

    if(perserveFileDate):
        shutil.copystat(src, dst)

其他回答

与公认的答案类似,如果您还想确保在目标路径中创建任何(不存在的)文件夹,以下代码块可能会很有用。

from os import path, makedirs
from shutil import copyfile
makedirs(path.dirname(path.abspath(destination_path)), exist_ok=True)
copyfile(source_path, destination_path)

正如公认的答案所指出的,这些行将覆盖目标路径上存在的任何文件,因此有时在该代码块之前添加:if not path.exists(destination_path):可能会很有用。

从Python 3.5开始,您可以对小文件(例如:文本文件、小jpegs)执行以下操作:

from pathlib import Path

source = Path('../path/to/my/file.txt')
destination = Path('../path/where/i/want/to/store/it.txt')
destination.write_bytes(source.read_bytes())

write_bytes将覆盖目标位置的任何内容

shutil模块提供了一些对文件的高级操作。它支持文件复制和删除。

请参考下表了解您的用例。

Function Utilize
File Object
Preserve File
Metadata
Preserve
Permissions
Supports
Directory Dest.
shutil.copyfileobj
shutil.copyfile
shutil.copy2
shutil.copy

对于大型文件,我逐行读取文件,并将每一行读取到一个数组中。然后,一旦数组达到一定大小,就将其追加到新文件中。

for line in open("file.txt", "r"):
    list.append(line)
    if len(list) == 1000000: 
        output.writelines(list)
        del list[:]

您可以使用shutil软件包中的复制功能之一:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Function              preserves     supports          accepts     copies other
                      permissions   directory dest.   file obj    metadata  
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
shutil.copy              ✔             ✔                 ☐           ☐
shutil.copy2             ✔             ✔                 ☐           ✔
shutil.copyfile          ☐             ☐                 ☐           ☐
shutil.copyfileobj       ☐             ☐                 ✔           ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

例子:

import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')