126

How to copy all the files present in one directory to another directory using Python. I have the source path and the destination path as string.

leocrimson
  • 702
  • 1
  • 11
  • 25
hidayat
  • 9,493
  • 13
  • 51
  • 66
  • 2
    [How do I copy an entire directory of files into an existing directory using Python?](http://stackoverflow.com/questions/1868714/how-do-i-copy-an-entire-directory-of-files-into-an-existing-directory-using-pyth) – storm_m2138 Mar 11 '16 at 21:19

8 Answers8

165

You can use os.listdir() to get the files in the source directory, os.path.isfile() to see if they are regular files (including symbolic links on *nix systems), and shutil.copy to do the copying.

The following code copies only the regular files from the source directory into the destination directory (I'm assuming you don't want any sub-directories copied).

import os
import shutil
src_files = os.listdir(src)
for file_name in src_files:
    full_file_name = os.path.join(src, file_name)
    if os.path.isfile(full_file_name):
        shutil.copy(full_file_name, dest)
K Erlandsson
  • 13,408
  • 6
  • 51
  • 67
GreenMatt
  • 18,244
  • 7
  • 53
  • 79
  • Should dest be something like C:\myfolder or C:\myfolder\filename.ext ? – Steve Byrne Mar 11 '18 at 10:01
  • 5
    @StevenByrne Can be either, depending on if you want to also rename the file. If not, then `dest` is the directory name. `shutil.copy(src, dst)` "copies the file src to the file or directory dst.... If dst specifies a directory, the file will be copied into dst using the base filename from src." –  Apr 11 '18 at 19:43
  • 1
    Small improvement: leave the src_files and do `for fn in os.listdir(src)` – Timo Nov 12 '20 at 10:46
39

If you don't want to copy the whole tree (with subdirs etc), use or glob.glob("path/to/dir/*.*") to get a list of all the filenames, loop over the list and use shutil.copy to copy each file.

for filename in glob.glob(os.path.join(source_dir, '*.*')):
    shutil.copy(filename, dest_dir)
Steven
  • 28,002
  • 5
  • 61
  • 51
  • 2
    Note: You might have to check the glob results with os.path.isfile() to be sure they are filenames. See also GreenMatt's answer. While glob does return only the filename like os.listdir, it still returns directory names as well. The '*.*' pattern might be enough, as long as you don't have extensionless filenames, or dots in directory names. – Steven Aug 04 '10 at 08:22
  • This doesn't copy subdirs – citynorman Jan 12 '19 at 03:00
28

Look at shutil in the Python docs, specifically the copytree command.

If the destination directory already exists, try:

shutil.copytree(source, destination, dirs_exist_ok=True)
codersl
  • 2,222
  • 4
  • 30
  • 33
Doon
  • 19,719
  • 3
  • 40
  • 44
5
import os
import shutil
os.chdir('C:\\') #Make sure you add your source and destination path below

dir_src = ("C:\\foooo\\")
dir_dst = ("C:\\toooo\\")

for filename in os.listdir(dir_src):
    if filename.endswith('.txt'):
        shutil.copy( dir_src + filename, dir_dst)
    print(filename)
5
def recursive_copy_files(source_path, destination_path, override=False):
    """
    Recursive copies files from source  to destination directory.
    :param source_path: source directory
    :param destination_path: destination directory
    :param override if True all files will be overridden otherwise skip if file exist
    :return: count of copied files
    """
    files_count = 0
    if not os.path.exists(destination_path):
        os.mkdir(destination_path)
    items = glob.glob(source_path + '/*')
    for item in items:
        if os.path.isdir(item):
            path = os.path.join(destination_path, item.split('/')[-1])
            files_count += recursive_copy_files(source_path=item, destination_path=path, override=override)
        else:
            file = os.path.join(destination_path, item.split('/')[-1])
            if not os.path.exists(file) or override:
                shutil.copyfile(item, file)
                files_count += 1
    return files_count
Constantinius
  • 34,183
  • 8
  • 77
  • 85
4

Here is another example of a recursive copy function that lets you copy the contents of the directory (including sub-directories) one file at a time, which I used to solve this problem.

import os
import shutil

def recursive_copy(src, dest):
    """
    Copy each file from src dir to dest dir, including sub-directories.
    """
    for item in os.listdir(src):
        file_path = os.path.join(src, item)

        # if item is a file, copy it
        if os.path.isfile(file_path):
            shutil.copy(file_path, dest)

        # else if item is a folder, recurse 
        elif os.path.isdir(file_path):
            new_dest = os.path.join(dest, item)
            os.mkdir(new_dest)
            recursive_copy(file_path, new_dest)

EDIT: If you can, definitely just use shutil.copytree(src, dest). This requires that that destination folder does not already exist though. If you need to copy files into an existing folder, the above method works well!

Dustin Michels
  • 2,951
  • 2
  • 19
  • 31
0

The top rated answer will throw a runtime error because it tries to join a list with a file name on line 5, when it's supposed to be joining one string with another string. Create another variable called pathSrc and use that in the join argument. I would also create another variable called pathDest and concatenate it with file_name on the last line. I also imported the method needed from shutil rather than the whole module.

import os
from shutil import copyfile
pathSrc = "the folder where the src files are"
pathDest = "the folder where the dest files are going"
src_files = os.listdir(src)
for file_name in src_files:
    full_file_name = os.path.join(pathSrc, file_name)
    if os.path.isfile(full_file_name):
        shutil.copy(full_file_name, pathDest + file_name)
0

Why not a single line?

import os
import shutil
dest = 'path/to/destination/folder'
src = 'path/to/source/folder/' # mind the '/' at the end
[shutil.copy(src+fn, dest) for fn in os.listdir(src)]

Or with a error handling condition

import os
import shutil
dest = 'path/to/destination/folder'
src = 'path/to/source/folder/' # mind the '/' at the end
try:    
    [shutil.copy(src+fn, dest) for fn in os.listdir(src)]
except:
    print('files already exist in', dest)
rmj
  • 119
  • 3