How to copy a directory recursively in Python

How to copy a directory recursively in Python:

In this post, we will learn how to copy a directory in Python recursively. We will use shutil package to do the copying. copytree is the method that is used to copy a directory recursively.

I will show you how to use copytree with example.

Definition of shutil.copytree

copytree is defined as below:

shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False, dirs_exist_ok=False)

This method copies the content recursively. It returns the destination directory.

Here,

  • src is the source directory.
  • dst is the destination directory.
  • dirs_exist_ok is a flag, to indicate if an exception should be raised, if the destination directory or any missing parent directory already exists.
  • symlinks is an optional value. If it is true, symbolic links in the source tree are represented in the destination tree. If false or not available, the metadata and contents of the linked files are copied.
  • If the file pointed by the symlinks doesn’t exist, it throws one error. We can add ignore_dangling_symlinks as true to silence this.
  • ignore is used to ignore specific paths in the copy operation. It must be a callable. It is called with two parameters: the first one is the directory path currently visited by the copytree and the second one is the list of paths in the directory as returned by the os.listdir() method. This method will return the list of names that should not be copied.

This method will be called once for each directory that copytree finds while iterating recursively.

  • copy_function is an optional value and it should be a callable. This is used to copy each file. It must take the source and destination paths. It uses copy2() method by default.

Example program:

Let’s take a look at the below example:

import shutil

src = './source'
dst = './destination'

try:
    shutil.copytree(src, dst)
except shutil.Error as e1:
    print('Error occurred ', e1)
except OSError as e2:
    print('OSError ', e2)

It will copy all contents of the folder source to the folder destination recursively. We are using try-except block to handle all exceptions.

Ignoring files while copying:

As mentioned before, we can use the ignore parameter to specify files to ignore while copying using copytree. For example:

import shutil

src = './source'
dst = './destination'


def ignore_files(dir, paths):
    to_ignore_files = []
    for path in paths:
        if path.endswith('.png'):
            to_ignore_files.append(path)
    return to_ignore_files


try:
    shutil.copytree(src, dst, ignore=ignore_files)
except shutil.Error as e1:
    print('Error occurred ', e1)
except OSError as e2:
    print('OSError ', e2)

In this example, we are passing ignore_files to ignore. It will ignore all files those are ending with .png. It iterates through the paths and returns one array holding all paths of .png files.

Copy items to an existing directory:

If the destination directory exists, and if you execute the above function, it will throw one exception.

OSError  [Errno 17] File exists: './destination'

For that, we can mark dirs_exist_ok as True to copy the items to an existing directory.

import shutil

src = './source'
dst = './destination'

try:
    shutil.copytree(src, dst, dirs_exist_ok=True)
except shutil.Error as e1:
    print('Error occurred ', e1)
except OSError as e2:
    print('OSError ', e2)

You might also like: