How to copy files?

2,815,586

Solution 1

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 src to a file named dst. Both src and dst need to be the entire filename of the files, including path.
  • 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.
  • With copy, src and dst are path names given as strs.

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.

Solution 2

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

Solution 3

copy2(src,dst) is often more useful than copyfile(src,dst) because:

  • it allows dst to be a directory (instead of the complete target filename), in which case the basename of src is 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

Solution 4

In Python, you can copy the files using


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)

Solution 5

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')
Share:
2,815,586
Matt
Author by

Matt

I'm just some guy who does some programming stuff.

Updated on July 08, 2022

Comments

  • Matt
    Matt almost 2 years

    How do I copy a file in Python?

  • pi.
    pi. about 15 years
    I 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.
  • Kevin Horn
    Kevin Horn over 14 years
    Note that not all metadata will be copied, depending on your platform.
  • Vijay
    Vijay about 10 years
    I am trying to randomly copy 100k files from 1 million files. copyfile is considerably faster than copy2
  • owns
    owns almost 9 years
    this 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.
  • rassa45
    rassa45 almost 9 years
    Yes, 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).
  • owns
    owns almost 9 years
    Very true. Coding for teaching and coding for efficiency are very different.
  • Kevin Meier
    Kevin Meier over 7 years
    This depends on the platform, so i would not use is.
  • rassa45
    rassa45 over 7 years
    @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.
  • buhtz
    buhtz about 7 years
    Such a call is unsecure. Please refere to the subproces docu about it.
  • owns
    owns about 7 years
    looking at the source - writelines calls write, 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.
  • Corey Goldberg
    Corey Goldberg almost 7 years
    this is not portable, and unnecessary since you can just use shutil.
  • Corey Goldberg
    Corey Goldberg almost 7 years
    this is not portable, and unnecessary since you can just use shutil.
  • Baris Demiray
    Baris Demiray almost 7 years
    Hmm why Python, then?
  • maxschlepzig
    maxschlepzig almost 7 years
    Even when shutil is not available - subprocess.run() (without shell=True!) is the better alternative to os.system().
  • waterbyte
    waterbyte over 5 years
    Note that it is not an atomic operation. Take care using it in a threaded application.
  • MilkyWay90
    MilkyWay90 over 5 years
    Maybe detect the operating system before starting (whether it's DOS or Unix, because those are the two most used)
  • zwep
    zwep over 5 years
    Note that it cant handle abbreviations like ~, but it can deal with relative paths
  • Jack M
    Jack M over 5 years
    @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.
  • Alexei Martianov
    Alexei Martianov over 5 years
    To create all intermediate-level destination directories you could use os.makedirs() before copying, details here stackoverflow.com/questions/12842997/…
  • Hiadore
    Hiadore about 5 years
    shutil is more portable
  • Raúl Salinas-Monteagudo
    Raúl Salinas-Monteagudo about 5 years
    The 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.
  • miike3459
    miike3459 about 5 years
    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.
  • luckydonald
    luckydonald about 5 years
    Isn't that missing the .close() on all of those open(...)s?
  • Sundeep471
    Sundeep471 about 5 years
    No need of .close(), as we are NOT STORING the file pointer object anywhere(neither for the src file nor for the destination file).
  • Marcel Waldvogel
    Marcel Waldvogel about 5 years
    Using 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
    Marcel Waldvogel about 5 years
    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
    Marcel Waldvogel about 5 years
    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. docs.python.org/3/library/io.html#io.BufferedReader
  • Marcel Waldvogel
    Marcel Waldvogel about 5 years
    And 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.
  • maxschlepzig
    maxschlepzig about 5 years
    Same suboptimal memory-wasting approach as yellow01's answer.
  • maxschlepzig
    maxschlepzig about 5 years
    Why do you list so many bad alternatives to the shutil copy functions?
  • Jean-François Fabre
    Jean-François Fabre about 5 years
    shutil 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
    Jean-François Fabre about 5 years
    try that with filenames with spaces in it.
  • Jean-François Fabre
    Jean-François Fabre about 5 years
    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
    Jean-François Fabre about 5 years
    at least it doesn't repeat the same solutions over and over again.
  • maxschlepzig
    maxschlepzig about 5 years
    This 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.
  • gman
    gman over 4 years
    shutil does not actually copy files. There's a big fat warning right at the top of the docs. "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
    gman over 4 years
    shutil does not actually copy files. There's a big fat warning right at the top of the docs. "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."
  • Martijn Pieters
    Martijn Pieters about 4 years
    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
    Martijn Pieters about 4 years
    In Python 3.8 this has received some significant speed boosts (~50% faster, depending on OS).
  • ingyhere
    ingyhere almost 4 years
    You should run copy then copystat to preserve file metadata. In Python 3.3+ copystat also copies extended attributes.
  • Debvrat Varshney
    Debvrat Varshney almost 4 years
    copy or copyfile does not seem to replace the file if dst already exists 🤔. Getting a SameFileError
  • AO_
    AO_ over 3 years
    If you want some pictures to help with clarity: ao.gl/how-to-copy-a-file-in-python
  • KansaiRobot
    KansaiRobot almost 3 years
    dst as a folder throws an exception
  • Scrooge McDuck
    Scrooge McDuck over 2 years
    equivalent of cp
  • Admin
    Admin over 2 years
    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.
  • Eric Aya
    Eric Aya over 2 years
    This 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.
  • user3804598
    user3804598 over 2 years
    it handles relative paths nicely
  • kontur
    kontur over 2 years
    And if the file name remains, you can copy to the destination folder: shutil.copy(os.path.join(old_dir, file), new_dir)
  • wovano
    wovano about 2 years
  • t3chb0t
    t3chb0t about 2 years
    What a mess! Who designed these APIs :-\
  • t3chb0t
    t3chb0t about 2 years
    @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.
  • otocan
    otocan almost 2 years
    Note that shutil.copy also allows dest to be a directory, at least in current versions (I'm using python 3.8)