如何在Python中复制文件?
如何在Python中复制文件?
我想提出一个不同的解决方案。
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")
对于大家推荐的答案,如果您不想使用标准模块,或者像我一样完全删除了它们,更喜欢使用核心C方法而不是编写不良Python方法
shutil的工作方式是符号链接/硬链接安全的,但由于os.path.normpath()
包含一个while(nt,mac)或for(posix)循环,用于测试shutil.copyfile()
中的src
和dst
是否相同,因此速度较慢。
如果您确定src
和dst
永远不会是同一个文件,则此部分大多数情况下是不需要的,否则可能可以使用更快的C方法。
(请注意,仅因为一个模块可能是C并不意味着它本质上更快,在使用之前请确保您使用的是编写良好的模块)
在进行初始测试之后,copyfile()
在动态元组(src,dst)
上运行for循环,测试特殊文件(例如posix中的套接字或设备)。
最后,如果follow_symlinks
为False,则copyfile()
会使用os.path.islink()
测试src
是否为符号链接,在Windows和Linux上可能是nt.lstat()
或posix.lstat()
(os.lstat()
),在Mac上可能是Carbon.File.ResolveAliasFile(s, 0)[2]
。
如果该测试返回True,则复制符号链接/硬链接的核心代码如下:
os.symlink(os.readlink(src), dst)
在posix中,硬链接是通过posix.link()
完成的,尽管可以通过os.link()
调用,但shutil.copyfile()
并不会调用它。
(可能是因为检查硬链接的唯一方法是对我们知道的第一个inode的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)
copyfile()
的第二个测试之后,因此如果你懒得去做,它并不是一个可怕的选择,但由于轻微膨胀,初始测试将会有点慢,所以在大规模复制时可能会有些缺陷。您可以使用system。
对于类Unix系统:
import os
copy_file = lambda src_file, dest: os.system(f"cp {src_file} {dest}")
copy_file("./file", "../new_dir/file")
这里是一个使用"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)
您可以使用 os.link 创建文件的硬链接:
os.link(source, dest)
这不是一个独立的克隆,但如果您计划仅读取(不修改)新文件并且其内容必须与原始文件保持相同,则这将非常有效。它还有一个好处,即如果您想检查副本是否已经存在,则可以比较硬链接(使用os.stat),而不是它们的内容。
在Linux中,命令cp
带有键
cp -al
创建硬链接。因此,硬链接可以被视为副本。有时候,一个人需要的正是这种行为(从不同位置访问文件内容),而不需要单独的副本。
shutil.copy(src, dst)
以下命令用于复制带有元数据信息的文件:
shutil.copystat(src, dst)
copy
然后再运行 copystat
以保留文件元数据。在 Python 3.3+ 中,copystat
还会复制扩展属性。 - ingyhereshutil.copy(src, dst, *, follow_symlinks=True)
shutil.copy(源路径,目标路径,*,follow_symlinks=True)