shutil - How do I copy an entire directory of files into an existing directory using Python?

ID : 10265

viewed : 26

Tags : pythonshutilcopytreepython

Top 5 Answer for shutil - How do I copy an entire directory of files into an existing directory using Python?

vote vote

90

Here's a solution that's part of the standard library:

from distutils.dir_util import copy_tree copy_tree("/a/b/c", "/x/y/z") 

See this similar question.

Copy directory contents into a directory with python

vote vote

83

This limitation of the standard shutil.copytree seems arbitrary and annoying. Workaround:

import os, shutil def copytree(src, dst, symlinks=False, ignore=None):     for item in os.listdir(src):         s = os.path.join(src, item)         d = os.path.join(dst, item)         if os.path.isdir(s):             shutil.copytree(s, d, symlinks, ignore)         else:             shutil.copy2(s, d) 

Note that it's not entirely consistent with the standard copytree:

  • it doesn't honor symlinks and ignore parameters for the root directory of the src tree;
  • it doesn't raise shutil.Error for errors at the root level of src;
  • in case of errors during copying of a subtree, it will raise shutil.Error for that subtree instead of trying to copy other subtrees and raising single combined shutil.Error.
vote vote

76

Python 3.8 introduced the dirs_exist_ok argument to shutil.copytree:

Recursively copy an entire directory tree rooted at src to a directory named dst and return the destination directory. dirs_exist_ok dictates whether to raise an exception in case dst or any missing parent directory already exists.

Therefore, with Python 3.8+ this should work:

import shutil  shutil.copytree('bar', 'foo') shutil.copytree('baz', 'foo', dirs_exist_ok=True) 
vote vote

63

In slight improvement on atzz's answer to the function where the above function always tries to copy the files from source to destination.

def copytree(src, dst, symlinks=False, ignore=None):     if not os.path.exists(dst):         os.makedirs(dst)     for item in os.listdir(src):         s = os.path.join(src, item)         d = os.path.join(dst, item)         if os.path.isdir(s):             copytree(s, d, symlinks, ignore)         else:             if not os.path.exists(d) or os.stat(s).st_mtime - os.stat(d).st_mtime > 1:                 shutil.copy2(s, d) 

In my above implementation

  • Creating the output directory if not already exists
  • Doing the copy directory by recursively calling my own method.
  • When we come to actually copying the file I check if the file is modified then only we should copy.

I am using above function along with scons build. It helped me a lot as every time when I compile I may not need to copy entire set of files.. but only the files which are modified.

vote vote

57

A merge one inspired by atzz and Mital Vora:

#!/usr/bin/python import os import shutil import stat def copytree(src, dst, symlinks = False, ignore = None):   if not os.path.exists(dst):     os.makedirs(dst)     shutil.copystat(src, dst)   lst = os.listdir(src)   if ignore:     excl = ignore(src, lst)     lst = [x for x in lst if x not in excl]   for item in lst:     s = os.path.join(src, item)     d = os.path.join(dst, item)     if symlinks and os.path.islink(s):       if os.path.lexists(d):         os.remove(d)       os.symlink(os.readlink(s), d)       try:         st = os.lstat(s)         mode = stat.S_IMODE(st.st_mode)         os.lchmod(d, mode)       except:         pass # lchmod not available     elif os.path.isdir(s):       copytree(s, d, symlinks, ignore)     else:       shutil.copy2(s, d) 
  • Same behavior as shutil.copytree, with symlinks and ignore parameters
  • Create directory destination structure if non existant
  • Will not fail if dst already exists

Top 3 video Explaining shutil - How do I copy an entire directory of files into an existing directory using Python?

Related QUESTION?