提问人:Matt 提问时间:9/24/2008 最后编辑:Peter MortensenMatt 更新时间:7/14/2023 访问量:3541791
如何复制文件
How to copy files
答:
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
dst
- 目标位置必须是可写的;否则,将引发异常。
IOError
- 如果已存在,则将其替换。
dst
- 特殊文件(如字符或块设备和管道)无法使用此功能复制。
- 使用 和 是以 s 形式给出的路径名。
copy
src
dst
str
另一种要查看的方法是 shutil.copy2()。
它与此类似,但保留了更多元数据(例如时间戳)。shutil
如果使用操作,请使用 而不是 。 将只接受字符串。os.path
copy
copyfile
copyfile
评论
FileNotFoundError: Directory does not exist: foo/
使用 shutil 模块。
copyfile(src, dst)
将名为 src 的文件的内容复制到名为 dst 的文件中。目标位置必须是可写的;否则,将引发 IOError 异常。如果 dst 已存在,它将被替换。特殊文件(如字符或块设备和管道)无法使用此功能复制。src 和 dst 是以字符串形式给出的路径名。
查看 filesys 以了解标准 Python 模块中可用的所有文件和目录处理函数。
copy2(src,dst
) 通常比 copyfile(src,dst)
更有用,因为:
- 它允许是一个目录(而不是完整的目标文件名),在这种情况下,basename 用于创建新文件;
dst
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
复制文件是一个相对简单的操作,如下面的示例所示,但您应该改用 shutil stdlib 模块。
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)
目录和文件复制示例,来自 Tim Golden 的 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"
您可以使用 .os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
或者就像我所做的那样,
os.system('cp '+ rawfile + ' rawdata.dat')
where 是我在程序中生成的名称。rawfile
这是仅限 Linux 的解决方案。
评论
shutil
subprocess.run()
shell=True
os.system()
subprocess.run()
正如@maxschlepzig所建议的那样,在调用外部程序时,这是向前迈出的一大步。但是,为了灵活性和安全性,请使用传递命令行的形式。(但是,对于复制,建议朋友不要调用外部程序。['cp', rawfile, 'rawdata.dat']
shutil
功能 | 复制 元数据 |
复制 权限 |
使用文件对象 | 目标 可能是目录 |
---|---|---|---|---|
shutil.copy | 不 | 是的 | 不 | 是的 |
shutil.copy文件 | 不 | 不 | 不 | 不 |
shutil.copy2 | 是的 | 是的 | 不 | 是的 |
shutil.copyfileobj | 不 | 不 | 是的 | 不 |
评论
shutil.copy2()
函数也无法复制所有文件元数据。
对于大文件,我逐行读取文件,并将每一行读入数组。然后,一旦数组达到一定大小,将其附加到一个新文件中。
for line in open("file.txt", "r"):
list.append(line)
if len(list) == 1000000:
output.writelines(list)
del list[:]
评论
for l in open('file.txt','r'): output.write(l)
output.write(read(n)); output.flush()
n
writelines()
write()
shutil
shutil
用于复制文件subprocess.call
from subprocess import call
call("cp -p <file> <file>", shell=True)
评论
call
您可以使用 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')
评论
对于小文件和仅使用 Python 内置文件,可以使用以下单行代码:
with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())
对于文件太大或内存至关重要的应用程序来说,这不是最佳方法,因此 Swati 的答案应该是首选。
评论
首先,我制作了一份详尽的 shutil 方法备忘单供您参考。
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',]
}
其次,在示例中解释复制方法:
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)
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
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
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
shutil.copytree()
以递归方式复制根植于 src 的整个目录树,返回目标目录。
在 Python 中,您可以使用以下命令复制文件
import os
import shutil
import subprocess
1) 使用 shutil
模块复制文件
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(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
模块复制文件
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(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(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)
评论
用
open(destination, 'wb').write(open(source, 'rb').read())
以读取方式打开源文件,以写入方式写入目标文件。
评论
.close()
open(...)
with
read()
shutil
从 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
将覆盖目的地位置的任何内容
评论
这是一种简单的方法,无需任何模块。它与这个答案类似,但如果它是一个不适合 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
。
与接受的答案类似,如果您还想确保在目标路径中创建任何(不存在的)文件夹,以下代码块可能会派上用场。
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):
万一你已经走到了这一步。答案是您需要整个路径和文件名
import os
shutil.copy(os.path.join(old_dir, file), os.path.join(new_dir, file))
评论
在 Python 中复制文件有两种最佳方法。
1. 我们可以使用 shutil
模块
代码示例:
import shutil
shutil.copyfile('/path/to/file', '/path/to/new/file')
除了 copyfile 之外,还有其他方法可用,比如 copy、copy2 等,但 copyfile 在性能方面是最好的,
2.我们可以使用操作系统
模块
代码示例:
import os
os.system('cp /path/to/file /path/to/new/file')
另一种方法是使用子进程,但它不是可取的,因为它是调用方法之一,并且不安全。
评论
我想提出一个不同的解决方案。
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 的工作方式是符号链接/硬链接安全的,但由于包含 while (nt, mac) 或 for (posix) 循环,用于测试 if 和 are same inos.path.normpath()
src
dst
shutil.copyfile()
如果您知道某些 src
和 dst
永远不会是同一个文件,那么这部分基本上是不需要的,否则可能会使用更快的 C 方法。
(请注意,仅仅因为一个模块可能是 C 并不意味着它本身就更快,在你使用它之前,要知道你使用的东西实际上已经写得很好了)
在初始测试之后,在 的动态元组上运行 for 循环,测试特殊文件(例如 posix 中的套接字或设备)。copyfile()
(src, dst)
最后,如果为 False,则测试是否是带有 的符号链接,在 Windows 和 Linux 上或在 Mac 上,该符号链接在 or () 之间变化。
如果该测试解析为 True,则复制符号链接/硬链接的核心代码为:follow_symlinks
copyfile()
src
os.path.islink()
nt.lstat()
posix.lstat()
os.lstat()
Carbon.File.ResolveAliasFile(s, 0)[2]
os.symlink(os.readlink(src), dst)
posix 中的硬链接是用 完成的,尽管可以通过 调用,但它不会调用。
(可能是因为检查硬链接的唯一方法是对我们知道的第一个 inode 进行哈希映射(特别是),并假设这是硬链接目标)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()
评论