代码之家  ›  专栏  ›  技术社区  ›  Matt

如何在Python中复制文件?

  •  1736
  • Matt  · 技术社区  · 17 年前

    如何在Python中复制文件?

    14 回复  |  直到 5 年前
        1
  •  3854
  •   Nam G VU    5 年前

    shutil 有很多方法可以使用。其中之一是:

    import shutil
    
    shutil.copyfile(src, dst)
    
    # 2nd option
    shutil.copy(src, dst)  # dst can be a folder; use shutil.copy2() to preserve timestamp
    
    • 复制名为的文件的内容 src 到名为的文件 dst 两者都有 src公司 夏令时 需要是文件的完整文件名,包括路径。
    • 目标位置必须可写;否则,a IOError 将引发异常。
    • 如果 夏令时 已存在,将被替换。
    • 此功能无法复制字符或块设备和管道等特殊文件。
    • 具有 copy , src公司 夏令时 路径名是否为 str s

    又一个 关机 看的方法是 shutil.copy2() 它与之相似,但保留了更多的元数据(例如时间戳)。

    如果你使用 os.path 操作,使用 复制 而不是 copyfile . 复制文件 将只接受字符串。

        2
  •  1760
  •   Stefan    5 年前
    功能 副本
    元数据
    副本
    许可
    使用文件对象 目的地
    可能是目录
    shutil.copy 是的 是的
    shutil.copyfile
    shutil.copy2 是的 是的 是的
    shutil.copyfileobj 是的
        3
  •  863
  •   Jonathan H    9 年前

    copy2(src,dst) 通常比 copyfile(src,dst) 因为:

    • 它允许 dst 成为a 目录 (而不是完整的目标文件名),在这种情况下 basename 属于的 src 用于创建新文件;
    • 它在文件元数据中保留了原始的修改和访问信息(mtime和atime)(但是,这会带来轻微的开销)。

    下面是一个简短的例子:

    import shutil
    shutil.copy2('/src/dir/file.ext', '/dst/dir/newname.ext') # complete target filename given
    shutil.copy2('/src/file.ext', '/dst/dir') # target filename is /dst/dir/file.ext
    
        4
  •  175
  •   Community Mohan Dere    6 年前

    在Python中,您可以使用以下命令复制文件


    import os
    import shutil
    import subprocess
    

    1) 使用复制文件 关机 模块

    shutil.copyfile 签名

    shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)
    
    # example    
    shutil.copyfile('source.txt', 'destination.txt')
    

    shutil.copy 签名

    shutil.copy(src_file, dest_file, *, follow_symlinks=True)
    
    # example
    shutil.copy('source.txt', 'destination.txt')
    

    shutil.copy2 签名

    shutil.copy2(src_file, dest_file, *, follow_symlinks=True)
    
    # example
    shutil.copy2('source.txt', 'destination.txt')  
    

    shutil.copyfileobj 签名

    shutil.copyfileobj(src_file_object, dest_file_object[, length])
    
    # example
    file_src = 'source.txt'  
    f_src = open(file_src, 'rb')
    
    file_dest = 'destination.txt'  
    f_dest = open(file_dest, 'wb')
    
    shutil.copyfileobj(f_src, f_dest)  
    

    2) 使用复制文件 操作系统 模块

    os.popen 签名

    os.popen(cmd[, mode[, bufsize]])
    
    # example
    # In Unix/Linux
    os.popen('cp source.txt destination.txt') 
    
    # In Windows
    os.popen('copy source.txt destination.txt')
    

    os.system 签名

    os.system(command)
    
    
    # In Linux/Unix
    os.system('cp source.txt destination.txt')  
    
    # In Windows
    os.system('copy source.txt destination.txt')
    

    3) 使用复制文件 子流程 模块

    subprocess.call 签名

    subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
    
    # example (WARNING: setting `shell=True` might be a security-risk)
    # In Linux/Unix
    status = subprocess.call('cp source.txt destination.txt', shell=True) 
    
    # In Windows
    status = subprocess.call('copy source.txt destination.txt', shell=True)
    

    subprocess.check_output 签名

    subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
    
    # example (WARNING: setting `shell=True` might be a security-risk)
    # In Linux/Unix
    status = subprocess.check_output('cp source.txt destination.txt', shell=True)
    
    # In Windows
    status = subprocess.check_output('copy source.txt destination.txt', shell=True)
    

        5
  •  171
  •   maxschlepzig    8 年前

    您可以使用 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')
    
        6
  •  107
  •   Eric O. Lebigot    8 年前

    复制文件是一个相对简单的操作,如下面的示例所示,但您应该使用 shutil stdlib module 为了这个。

    def copyfileobj_example(source, dest, buffer_size=1024*1024):
        """      
        Copy a file from source to dest. source and dest
        must be file-like objects, i.e. any object with a read or
        write method, like for example StringIO.
        """
        while True:
            copy_buffer = source.read(buffer_size)
            if not copy_buffer:
                break
            dest.write(copy_buffer)
    

    如果你想按文件名复制,你可以这样做:

    def copyfile_example(source, dest):
        # Beware, this example does not handle any edge cases!
        with open(source, 'rb') as src, open(dest, 'wb') as dst:
            copyfileobj_example(src, dst)
    
        7
  •  80
  •   flying sheep    11 年前

    使用 shutil module .

    copyfile(src, dst)
    

    复制名为的文件的内容 src公司 到名为的文件 夏令时 目标位置必须是可写的;否则,将引发IOError异常。如果 夏令时 已存在,将被替换。此功能无法复制字符或块设备和管道等特殊文件。 src公司 夏令时 是以字符串形式给出的路径名。

    看一看 filesys 对于标准Python模块中可用的所有文件和目录处理函数。

        8
  •  50
  •   Noam Manos wim    15 年前

    目录和文件复制示例, from Tim Golden's Python Stuff :

    import os
    import shutil
    import tempfile
    
    filename1 = tempfile.mktemp (".txt")
    open (filename1, "w").close ()
    filename2 = filename1 + ".copy"
    print filename1, "=>", filename2
    
    shutil.copy (filename1, filename2)
    
    if os.path.isfile (filename2): print "Success"
    
    dirname1 = tempfile.mktemp (".dir")
    os.mkdir (dirname1)
    dirname2 = dirname1 + ".copy"
    print dirname1, "=>", dirname2
    
    shutil.copytree (dirname1, dirname2)
    
    if os.path.isdir (dirname2): print "Success"
    
        9
  •  33
  •   user davidism    7 年前

    对于小文件和仅使用Python内置程序,您可以使用以下一行代码:

    with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())
    

    对于文件太大或内存至关重要的应用程序来说,这不是最佳方式,因此 Swati's 答案应该是首选。

        10
  •  31
  •   fabda01    4 年前

    首先,我制作了一份详尽的备忘单 关机 方法供您参考。

    shutil_methods =
    {'copy':['shutil.copyfileobj',
              'shutil.copyfile',
              'shutil.copymode',
              'shutil.copystat',
              'shutil.copy',
              'shutil.copy2',
              'shutil.copytree',],
     'move':['shutil.rmtree',
             'shutil.move',],
     'exception': ['exception shutil.SameFileError',
                     'exception shutil.Error'],
     'others':['shutil.disk_usage',
                 'shutil.chown',
                 'shutil.which',
                 'shutil.ignore_patterns',]
    }
    

    其次,用例子解释复制的方法:

    1. shutil.copyfileobj(fsrc, fdst[, length]) 操纵打开的对象

      In [3]: src = '~/Documents/Head+First+SQL.pdf'
      In [4]: dst = '~/desktop'
      In [5]: shutil.copyfileobj(src, dst)
      AttributeError: 'str' object has no attribute 'read'
      
      # Copy the file object
      In [7]: with open(src, 'rb') as f1,open(os.path.join(dst,'test.pdf'), 'wb') as f2:
          ...:      shutil.copyfileobj(f1, f2)
      In [8]: os.stat(os.path.join(dst,'test.pdf'))
      Out[8]: os.stat_result(st_mode=33188, st_ino=8598319475, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067347, st_mtime=1516067335, st_ctime=1516067345)
      
    2. shutil.copyfile(src, dst, *, follow_symlinks=True) 复制并重命名

      In [9]: shutil.copyfile(src, dst)
      IsADirectoryError: [Errno 21] Is a directory: ~/desktop'
      # So dst should be a filename instead of a directory name
      
    3. shutil.copy() 复制而不预先显示元数据

      In [10]: shutil.copy(src, dst)
      Out[10]: ~/desktop/Head+First+SQL.pdf'
      
      # Check their metadata
      In [25]: os.stat(src)
      Out[25]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066425, st_mtime=1493698739, st_ctime=1514871215)
      In [26]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
      Out[26]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066427, st_mtime=1516066425, st_ctime=1516066425)
      # st_atime,st_mtime,st_ctime changed
      
    4. shutil.copy2() 复制时保留元数据

      In [30]: shutil.copy2(src, dst)
      Out[30]: ~/desktop/Head+First+SQL.pdf'
      In [31]: os.stat(src)
      Out[31]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067055, st_mtime=1493698739, st_ctime=1514871215)
      In [32]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
      Out[32]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067063, st_mtime=1493698739, st_ctime=1516067055)
      # Preserved st_mtime
      
    5. shutil.copytree()

      递归复制以src为根的整个目录树,返回目标目录。

        11
  •  18
  •   James Donnelly    11 年前

    截至 Python 3.5 您可以对小文件(即:文本文件、小jpeg)执行以下操作:

    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 将覆盖目的地位置的任何内容

        12
  •  17
  •   Marc    7 年前

    你可以使用 os.system('cp nameoffilegeneratedbyprogram /otherdirectory/') .

    或者,正如我所做的那样,

    os.system('cp '+ rawfile + ' rawdata.dat')
    

    哪里 rawfile 是我在程序中生成的名称。

    这是一个仅支持Linux的解决方案。

        13
  •  14
  •   rassa45    11 年前

    在Python中复制文件有两种最佳方法。

    1.我们可以使用 shutil 模块

    代码示例:

    import shutil
    shutil.copyfile('/path/to/file', '/path/to/new/file')
    

    除此之外,还有其他方法可供选择 复制文件 ,像copy、copy2等,但是 复制文件 在性能方面是最好的,

    2.我们可以使用 OS 模块

    代码示例:

    import os
    os.system('cp /path/to/file /path/to/new/file')
    

    另一种方法是使用子流程,但它不是首选的调用方法之一,也不安全。

        14
  •  13
  •   CaptAngryEyes deepdive    5 年前

    使用

    open(destination, 'wb').write(open(source, 'rb').read())
    

    以读取模式打开源文件,以写入模式写入目标文件。

        15
  •  12
  •   Jean-François Fabre    7 年前

    使用 subprocess.call 复制文件

    from subprocess import call
    call("cp -p <file> <file>", shell=True)
    
        16
  •  8
  •   Basj    5 年前

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

    for line in open("file.txt", "r"):
        list.append(line)
        if len(list) == 1000000: 
            output.writelines(list)
            del list[:]
    
        17
  •  8
  •   Leonardo Wildt    5 年前

    以防你走了这么远。答案是,您需要完整的路径和文件名

    import os
    
    shutil.copy(os.path.join(old_dir, file), os.path.join(new_dir, file))
    
        18
  •  8
  •   Raymond Toh    4 年前

    这是一种简单的方法,不需要任何模块。它类似于 this answer ,但如果它是一个不适合RAM的大文件,它也可以工作:

    with open('sourcefile', 'rb') as f, open('destfile', 'wb') as g:
        while True:
            block = f.read(16*1024*1024)  # work by blocks of 16 MB
            if not block:  # end of file
                break
            g.write(block)
    

    由于我们正在编写一个新文件,它不会保留修改时间等。
    然后我们可以使用 os.utime 如果需要的话。

        19
  •  5
  •   R J    5 年前

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

    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): 在这个代码块之前。

        20
  •  -1
  •   Al Baari    4 年前

    我想提出一个不同的解决方案。

    def copy(source, destination):
       with open(source, 'rb') as file:
           myFile = file.read()
       with open(destination, 'wb') as file:
           file.write(myFile)
    
    copy("foo.txt", "bar.txt")
    

    文件已打开,其数据将写入您选择的新文件。

        21
  •  -2
  •   Savai Maheshwari    7 年前

    对于每个人都推荐的答案,如果你不喜欢使用标准模块,或者像我一样完全删除了它们,那么你更喜欢使用更多的核心C方法,而不是编写糟糕的python方法

    shutil的工作方式是符号链接/硬链接安全的,但由于以下原因而相当缓慢 os.path.normpath() 包含while(nt,mac)或for(posix)循环,用于测试 src dst 都是一样的 shutil.copyfile()

    如果你确定的话,这部分基本上是不必要的 src公司 夏令时 永远不会是同一个文件,否则可能会使用更快的C方法。
    (请注意,仅仅因为一个模块可能是C语言,并不意味着它天生就更快,要知道你使用的东西在使用之前实际上已经写好了)

    在初始测试之后, copyfile() 在动态元组上运行for循环 (src, dst) ,测试特殊文件(如posix中的套接字或设备)。

    最后,如果 follow_symlinks 为假, copyfile() 测试如果 src公司 是一个符号链接 os.path.islink() ,随 nt.lstat() posix.lstat() ( os.lstat() )在Windows和Linux上,或 Carbon.File.ResolveAliasFile(s, 0)[2] 在Mac上。
    如果该测试解析为True,则复制符号链接/硬链接的核心代码为:

            os.symlink(os.readlink(src), dst)
    

    posix中的硬链接是用 posix.link() ,其中 shutil.copyfile() 不打电话,尽管可以通过电话呼叫 os.link() .
    (可能是因为检查硬链接的唯一方法是哈希映射 os.lstat() ( st_ino st_dev 具体来说)我们所知道的第一个索引节点,并假设这是硬链接目标)

    否则,文件复制是通过基本文件缓冲区完成的:

           with open(src, 'rb') as fsrc:
               with open(dst, 'wb') as fdst:
                   copyfileobj(fsrc, fdst)
    

    (与这里的其他答案类似)

    copyfileobj() 有点特别,因为它是缓冲区安全的,使用 length 参数以块的形式读取文件缓冲区:

    def copyfileobj(fsrc, fdst, length=16*1024):
        """copy data from file-like object fsrc to file-like object fdst"""
        while 1:
            buf = fsrc.read(length)
            if not buf:
                break
            fdst.write(buf)
    

    希望这个答案有助于揭示使用python核心机制进行文件复制的奥秘。 :)

    总的来说,shutil写得还不错,尤其是在第二次测试之后 copyfile() ,所以如果你懒惰,使用它并不是一个糟糕的选择,但由于轻微的膨胀,对于大容量副本来说,最初的测试会有点慢。