How do I copy an entire directory of files into an existing directory using Python?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The easiest way to copy a whole directory tree in Python is shutil.copytree. In modern Python, you can copy into an already existing destination by using dirs_exist_ok=True, which avoids the old need to manually iterate over files just to merge directories.
Copy the source directory into an existing parent directory
If you want source/ to appear as a subdirectory inside an existing destination directory, build the final path explicitly:
If source.name is "source", the result is /tmp/archive/source/....
Merge the contents directly into an existing directory
Sometimes you do not want the extra nested directory. You want the contents of source/ copied straight into the existing destination:
With dirs_exist_ok=True, Python copies files and subdirectories into destination and reuses the directory if it already exists.
What copytree preserves
By default, copytree uses copy2 for files, which means it copies the file contents and attempts to preserve metadata such as modification time. That makes it a better default than a manual loop with copy, especially for backup or packaging tasks.
You can also customize the copy behavior:
That example skips Python bytecode files while copying everything else.
A fallback for older Python versions
dirs_exist_ok=True was added in Python 3.8. If you are stuck on an older version, you need to walk the source tree yourself and copy entries one by one:
That works, but it is more verbose and easier to get wrong when nested directories become complex.
Overwrite behavior and safety
When dirs_exist_ok=True is enabled, existing files may be overwritten if the source contains a file with the same relative path. That is often exactly what you want, but it should be a deliberate decision.
If overwriting would be risky, preflight the copy first:
That gives you a list of destination files that would be replaced.
You can also validate the source and destination early:
Those small checks make batch copy utilities much more predictable.
Common Pitfalls
The biggest mistake is confusing "copy this directory into another directory" with "merge this directory's contents into another directory." Those are different operations, and the destination path you pass to copytree determines which one happens.
Another common issue is using copytree without dirs_exist_ok=True on an existing destination. In that case, Python raises FileExistsError.
Be careful with symbolic links and permissions if the directory tree comes from outside your control. Depending on the platform and options, copied results may not behave exactly like the original tree.
Finally, do not fall back to shell commands unless you truly need platform-specific behavior. shutil.copytree is portable, readable, and usually enough.
Summary
- Use
shutil.copytreefor recursive directory copies in Python. - Pass
dirs_exist_ok=Truewhen the destination already exists. - Copy to
destination / source.nameif you want a nested directory, or todestinationif you want to merge contents directly. - Use
ignore=or a preflight conflict check when you need more control. - For Python older than 3.8, copy items manually as a compatibility fallback.

