How do I copy a file in Python?
21 Answers
shutil has many methods you can use. One of which is:
import shutil
shutil.copyfile(src, dst)
# 2nd option
shutil.copy(src, dst) # dst can be a folder; use shutil.copy2() to preserve timestamp
- Copy the contents of the file named
srcto a file nameddst. Bothsrcanddstneed to be the entire filename of the files, including path. - The destination location must be writable; otherwise, an
IOErrorexception will be raised. - If
dstalready exists, it will be replaced. - Special files such as character or block devices and pipes cannot be copied with this function.
- With
copy,srcanddstare path names given asstrs.
Another shutil method to look at is shutil.copy2(). It's similar but preserves more metadata (e.g. time stamps).
If you use os.path operations, use copy rather than copyfile. copyfile will only accept strings.
-
56Note that not all metadata will be copied, depending on your platform. – Kevin Horn Oct 19 '09 at 20:50
-
22Note that it is not an atomic operation. Take care using it in a threaded application. – waterbyte Oct 22 '18 at 11:53
-
10Note that it cant handle abbreviations like `~`, but it can deal with relative paths – zwep Nov 27 '18 at 10:00
-
3@Owen Indeed it can, but the directory has to already exist. By the way, as long as the target directory already exists, `dst` can either end or not end with a trailing slash, it doesn't matter. – Jack M Dec 25 '18 at 14:34
-
1To create all intermediate-level destination directories you could use os.makedirs() before copying, details here https://stackoverflow.com/questions/12842997/how-to-copy-a-file-using-python – Alexei Martianov Jan 03 '19 at 05:37
-
2shutil does not actually copy files. There's [a big fat warning right at the top of the docs](https://docs.python.org/3/library/shutil.html). "this means that file owner and group are lost as well as ACLs. On Mac OS, the resource fork and other metadata are not used. This means that resources will be lost and file type and creator codes will not be correct. On Windows, file owners, ACLs and alternate data streams are not copied." – gman Nov 25 '19 at 03:04
-
2In Python 3.8 this has received some significant speed boosts (~50% faster, depending on OS). – Martijn Pieters Mar 20 '20 at 09:17
-
copy or copyfile does not seem to replace the file if dst already exists . Getting a SameFileError – Debvrat Varshney Aug 02 '20 at 22:35
-
If you want some pictures to help with clarity: https://ao.gl/how-to-copy-a-file-in-python/ – AO_ Aug 18 '20 at 06:49
-
dst as a folder throws an exception – KansaiRobot Aug 13 '21 at 15:40
-
*equivalent of* `cp` – Scrooge McDuck Oct 31 '21 at 20:28
-
it handles relative paths nicely – user3804598 Nov 26 '21 at 15:28
| Function | Copies metadata |
Copies permissions |
Uses file object | Destination may be directory |
|---|---|---|---|---|
| shutil.copy | No | Yes | No | Yes |
| shutil.copyfile | No | No | No | No |
| shutil.copy2 | Yes | Yes | No | Yes |
| shutil.copyfileobj | No | No | Yes | No |
-
2Note that [even the `shutil.copy2()` function cannot copy all file metadata](https://docs.python.org/3/library/shutil.html). – wovano Mar 11 '22 at 10:34
-
3
copy2(src,dst) is often more useful than copyfile(src,dst) because:
- it allows
dstto be a directory (instead of the complete target filename), in which case the basename ofsrcis used for creating the new file; - it preserves the original modification and access info (mtime and atime) in the file metadata (however, this comes with a slight overhead).
Here is a short example:
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
- 7,176
- 5
- 45
- 76
- 32,162
- 15
- 60
- 61
-
48I am trying to randomly copy 100k files from 1 million files. `copyfile` is considerably faster than `copy2` – Vijay May 07 '14 at 08:31
-
Note that shutil.copy also allows `dest` to be a directory, at least in current versions (I'm using python 3.8) – otocan May 26 '22 at 11:55
In Python, you can copy the files using
shutilmoduleosmodulesubprocessmodule
import os
import shutil
import subprocess
1) Copying files using shutil module
shutil.copyfile signature
shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copyfile('source.txt', 'destination.txt')
shutil.copy signature
shutil.copy(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copy('source.txt', 'destination.txt')
shutil.copy2 signature
shutil.copy2(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copy2('source.txt', 'destination.txt')
shutil.copyfileobj signature
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) Copying files using os module
os.popen signature
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 signature
os.system(command)
# In Linux/Unix
os.system('cp source.txt destination.txt')
# In Windows
os.system('copy source.txt destination.txt')
3) Copying files using subprocess module
subprocess.call signature
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 signature
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)
-
12Using single-string commands is bad coding style (flexibility, reliability and security), instead use `['copy', sourcefile, destfile]` syntax wherever possible, especially if the parameters are from user input. – Marcel Waldvogel Apr 29 '19 at 03:03
-
15Why do you list so many bad alternatives to the shutil copy functions? – maxschlepzig Apr 29 '19 at 11:08
-
17shutil is built-in, no need to provide non-portable alternatives. The answer could be actually improved by removing the system dependent solutions, and after that removal, this answer is just a copy of the existing answers / a copy of the documentation. – Jean-François Fabre Apr 29 '19 at 17:19
-
4`os.popen` is deprecated for a while now. and `check_output` doesn't return the status but the output (which is empty in the case of `copy/cp`) – Jean-François Fabre Apr 29 '19 at 18:12
-
3shutil does not actually copy files. There's [a big fat warning right at the top of the docs](https://docs.python.org/3/library/shutil.html). "this means that file owner and group are lost as well as ACLs. On Mac OS, the resource fork and other metadata are not used. This means that resources will be lost and file type and creator codes will not be correct. On Windows, file owners, ACLs and alternate data streams are not copied." – gman Nov 25 '19 at 03:03
-
1@Jean-FrançoisFabre System dependent solutions is exactly what I was looking for. The question is how to copy files in general not necessarily in a system-independet way so this answer is perfectly valid. – t3chb0t Apr 19 '22 at 09:57
You can use one of the copy functions from the shutil package:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Function preserves supports accepts copies other
permissions directory dest. file obj metadata
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
shutil.copy ✔ ✔ ☐ ☐
shutil.copy2 ✔ ✔ ☐ ✔
shutil.copyfile ☐ ☐ ☐ ☐
shutil.copyfileobj ☐ ☐ ✔ ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Example:
import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')
- 31,679
- 12
- 125
- 164
Copying a file is a relatively straightforward operation as shown by the examples below, but you should instead use the shutil stdlib module for that.
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)
If you want to copy by filename you could do something like this:
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)
- 86,421
- 44
- 210
- 254
- 20,133
- 7
- 37
- 59
-
25I noticed a while ago that the module is called shutil (singular) and not shutils (plural), and indeed it _is_ in Python 2.3. Nevertheless I leave this function here as an example. – pi. Mar 31 '09 at 15:20
Use the shutil module.
copyfile(src, dst)
Copy the contents of the file named src to a file named dst. The destination location must be writable; otherwise, an IOError exception will be raised. If dst already exists, it will be replaced. Special files such as character or block devices and pipes cannot be copied with this function. src and dst are path names given as strings.
Take a look at filesys for all the file and directory handling functions available in standard Python modules.
- 8,082
- 4
- 55
- 71
- 31,830
- 13
- 70
- 75
Directory and File copy example - From Tim Golden's Python Stuff:
http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html
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"
- 12,732
- 2
- 76
- 75
For small files and using only python built-ins, you can use the following one-liner:
with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())
This is not optimal way for applications where the file is too large or when memory is critical, thus Swati's answer should be preferred.
- 2,832
- 1
- 27
- 33
Firstly, I made an exhaustive cheatsheet of shutil methods for your reference.
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',]
}
Secondly, explain methods of copy in exmaples:
shutil.copyfileobj(fsrc, fdst[, length])manipulate opened objects
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)Copy and rename
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()Copy without preseving the metadata
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()Copy with preseving the metadata
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)
# Preseved st_mtime
shutil.copytree()
Recursively copy an entire directory tree rooted at src, returning the destination directory
- 4,960
- 7
- 46
- 70
- 17,381
- 14
- 68
- 114
You could use os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
or as I did it,
os.system('cp '+ rawfile + ' rawdata.dat')
where rawfile is the name that I had generated inside the program.
This is a Linux only solution
- 122,518
- 33
- 200
- 204
- 317
- 2
- 2
-
13this is not portable, and unnecessary since you can just use shutil. – Corey Goldberg Jun 12 '17 at 14:05
-
5Even when `shutil` is not available - `subprocess.run()` (without `shell=True`!) is the better alternative to `os.system()`. – maxschlepzig Jul 09 '17 at 11:52
-
2
-
2`subprocess.run()` as suggested by @maxschlepzig is a big step forward, when calling external programs. For flexibility and security however, use the `['cp', rawfile, 'rawdata.dat']` form of passing the command line. (However, for copying, `shutil` and friends are recommended over calling an external program.) – Marcel Waldvogel Apr 29 '19 at 03:09
-
2
As of Python 3.5 you can do the following for small files (ie: text files, small 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 will overwrite whatever was at the destination's location
- 3,795
- 1
- 32
- 32
-
4And then someone uses the code (accidentally or purposefully) on a large file… Using functions from `shutil` handles all the special cases for you and gives you peace of mind. – Marcel Waldvogel Apr 29 '19 at 03:21
-
10at least it doesn't repeat the same solutions over and over again. – Jean-François Fabre Apr 29 '19 at 18:16
shutil module offers some high-level operations on files. It supports file copying and removal.
Refer to the table below for your use case.
| Function | Utilize File Object |
Retain Metadata |
Retain Permissions |
Supports Directory Dest. |
|---|---|---|---|---|
| shutil.copyfileobj | ✔ | ⅹ | ⅹ | ⅹ |
| shutil.copyfile | ⅹ | ⅹ | ⅹ | ⅹ |
| shutil.copy2 | ⅹ | ✔ | ✔ | ✔ |
| shutil.copy | ⅹ | ⅹ | ✔ | ✔ |
- 812
- 1
- 5
- 26
For large files, what I did was read the file line by line and read each line into an array. Then, once the array reached a certain size, append it to a new file.
for line in open("file.txt", "r"):
list.append(line)
if len(list) == 1000000:
output.writelines(list)
del list[:]
- 3,408
- 1
- 28
- 43
-
2this seems a little redundant since the writer should handle buffering. `for l in open('file.txt','r'): output.write(l)` should work find; just setup the output stream buffer to your needs. or you can go by the bytes by looping over a try with `output.write(read(n)); output.flush()` where `n` is the number of bytes you'd like to write at a time. both of these also don't have an condition to check which is a bonus. – owns Jun 12 '15 at 17:30
-
1Yes, but I thought that maybe this could be easier to understand because it copies entire lines rather than parts of them (in case we don't know how many bytes each line is). – rassa45 Jun 13 '15 at 18:42
-
Very true. Coding for teaching and coding for efficiency are very different. – owns Jun 15 '15 at 17:47
-
@owns To add to this question a year later, `writelines()` has shown slightly better performance over `write()` since we don't waste time consistently opening a new filestream, and instead write new lines as one large bytefeed. – rassa45 Nov 30 '16 at 03:33
-
1looking at the source - writelines calls write, https://hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio.c. Also, the file stream is already open, so write wouldn't need to reopen it every time. – owns May 03 '17 at 00:24
-
3This is awful. It does unnecessary work for no good reason. It doesn't work for arbitrary files. The copy isn't byte-identical if the input has unusual line endings on systems like Windows. Why do you think that this might be easier to understand than a call to a copy function in `shutil`? Even when ignoring `shutil`, a simple block read/write loop (using unbuffered IO) is straight forward, would be efficient and would make much more sense than this, and thus is surely easier to teach and understand. – maxschlepzig Apr 29 '19 at 19:04
-
This also adds decoding / encoding overhead, and won’t work on binary data. **Just use `shutil.copyfile()`**, which on 3.8 has been improved further to use native OS support for fast file copying. It easily will take less than half the time from what this answer will take. – Martijn Pieters Mar 20 '20 at 09:13
Use subprocess.call to copy the file
from subprocess import call
call("cp -p <file> <file>", shell=True)
- 133
- 1
- 1
- 12
- 7,887
- 3
- 29
- 38
-
20
-
8Such a `call` is unsecure. Please refere to the subproces docu about it. – buhtz Apr 02 '17 at 07:57
-
5this is not portable, and unnecessary since you can just use shutil. – Corey Goldberg Jun 12 '17 at 14:05
-
4
-
Maybe detect the operating system before starting (whether it's DOS or Unix, because those are the two most used) – MilkyWay90 Nov 09 '18 at 15:51
open(destination, 'wb').write(open(source, 'rb').read())
Open the source file in read mode, and write to destination file in write mode.
- 131,796
- 23
- 122
- 195
- 1,393
- 18
- 24
-
2The idea is nice and the code is beautiful, but a proper copy() function can do more things, such as copying attributes (+x bit), or for example deleting the already-copied bytes in case a disk-full condition is found. – Raúl Salinas-Monteagudo Mar 29 '19 at 11:06
-
1**All** answers need explanation, even if it is one sentence. No explanation sets bad precedent and is not helpful in understanding the program. What if a complete Python noob came along and saw this, wanted to use it, but couldn't because they don't understand it? You want to be helpful to all in your answers. – miike3459 Mar 30 '19 at 22:19
-
3
-
No need of .close(), as we are NOT STORING the file pointer object anywhere(neither for the src file nor for the destination file). – Sundeep471 Apr 23 '19 at 21:19
-
AFAIK, it is undefined when the files are actually closed, @SundeepBorra. Using `with` (as in the example above) is recommended and not more complicated. Using `read()` on a raw file reads the entire file into memory, which may be too big. Use a standard function like from `shutil` so that you and whoever else is involved in the code does not need to worry about special cases. https://docs.python.org/3/library/io.html#io.BufferedReader – Marcel Waldvogel Apr 29 '19 at 03:17
-
2Same suboptimal memory-wasting approach as [yellow01's answer](https://stackoverflow.com/a/45694203/427158). – maxschlepzig Apr 29 '19 at 11:04
Here is a simple way to do it, without any module. It's similar to this answer, but has the benefit to also work if it's a big file that doesn't fit in 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)
Since we're writing a new file, it does not preserve the modification time, etc.
We can then use os.utime for this if needed.
- 36,818
- 81
- 313
- 561
In case you've come this far down. The answer is that you need the entire path and file name
import os
shutil.copy(os.path.join(old_dir, file), os.path.join(new_dir, file))
- 2,263
- 5
- 26
- 50
-
And if the file name remains, you can copy to the destination folder: `shutil.copy(os.path.join(old_dir, file), new_dir)` – kontur Dec 13 '21 at 13:35
Similar to the accepted answer, the following code block might come in handy if you also want to make sure to create any (non-existent) folders in the path to the destination.
from os import path, makedirs
from shutil import copyfile
makedirs(path.dirname(path.abspath(destination_path)), exist_ok=True)
copyfile(source_path, destination_path)
As the accepted answers notes, these lines will overwrite any file which exists at the destination path, so sometimes it might be useful to also add: if not path.exists(destination_path): before this code block.
- 4,325
- 2
- 21
- 28
Python provides in-built functions for easily copying files using the Operating System Shell utilities.
Following command is used to Copy File
shutil.copy(src,dst)
Following command is used to Copy File with MetaData Information
shutil.copystat(src,dst)
- 177
- 2
- 4
-
You should run `copy` then `copystat` to preserve file metadata. In Python 3.3+ `copystat` also copies extended attributes. – ingyhere May 22 '20 at 17:25
shutil.copy(src, dst, *, follow_symlinks=True)
- 21
- 3
-
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 07 '21 at 00:45
-
3This has already been mentioned in the other answers. *When answering older questions that already have answers, please make sure you provide either a novel solution or a significantly better explanation than existing answers.* – Eric Aya Nov 07 '21 at 12:07