Copy a File in Python with shutil

A CSV file may need a second copy in another directory while the original stays available. Python’s shutil module provides file-copy functions, and shutil.copy() writes the file at the destination while leaving the source in place.

I’ll show you how to copy a file with shutil.copy() and read the output to see that the source remains in place.

TL;DR: Use shutil.copy for a file

Use shutil.copy(source, destination) to copy a file and retain its permission mode. Choose copy2() when timestamps matter, or copyfile() when only the contents matter.

  • Pass a directory to copy() to keep the source filename.
  • Pass a full filename to copyfile().
  • Use copytree() for a directory and its contents.

What does copying a file in Python do?

A file copy writes the source file’s data to a separate destination path, leaving the source in place. The shutil module provides these operations in Python’s standard library, so a text file or CSV can be copied without reading or parsing its contents. I chose a directory target for the example because copy() keeps the source filename there.

FunctionUse it forDestinationWhat it preserves
shutil.copy()A regular file copyFile path or directoryContents and permission mode
shutil.copy2()Copy with timestamps when supportedFile path or directoryContents, mode, and additional metadata it can copy
shutil.copyfile()Contents onlyComplete file pathContents, not metadata
shutil.copyfileobj()Open streams or file-like objectsOpen destination objectData from current stream positions
shutil.copytree()A directory treeNew directory pathFiles and subdirectories

copy2() attempts to preserve more metadata than copy(), but no shutil function promises to reproduce every platform-specific detail. Python’s shutil documentation notes that ownership and access-control data may not carry over.

How to copy a file in Python step by step

The example uses pathlib paths for a source file and destination directory, then calls copy() because the copied file should keep its name.

Step 1: Choose a source file and destination directory

The source path names notes.txt. The destination path names the directory that will hold the copy, so copy() can retain the source filename.

Step 2: Copy the file with shutil.copy()

Save this as copy_file_demo.py and run python3 copy_file_demo.py from the same directory to see the copied path, contents, and source status.

from pathlib import Path
import shutil
import tempfile

with tempfile.TemporaryDirectory() as temp_dir:
    root = Path(temp_dir)
    source = root / "notes.txt"
    destination_dir = root / "backup"
    destination_dir.mkdir()
    source.write_text("Copying keeps the source file in place.\n", encoding="utf-8")

    copied_path = Path(shutil.copy(source, destination_dir))
    print(f"Copy path: {copied_path.name}")
    print(f"Copy contents: {copied_path.read_text(encoding='utf-8').strip()}")
    print(f"Source still exists: {source.exists()}")
adityagupta@askpython:~$ python3 copy_file_demo.py
Copy path: notes.txt
Copy contents: Copying keeps the source file in place.
Source still exists: True

[exit 0]
Terminal output from a Python shutil.copy example

Step 3: Verify the copy and source

The output shows the copied filename and contents, then confirms the original still exists. I ran this example with Python 3.14.7 and all three checks printed as expected.

What should you check before copying a file?

Check the destination first, because an existing file can be overwritten and the required destination form depends on the function.

CaseWhat happensWhat to do
Destination file existscopyfile() replaces it. copy() also overwrites the file at its target.Choose a unique destination or check before copying if the old copy must remain
Source and destination are the same filecopyfile() raises shutil.SameFileErrorCompare resolved paths before starting when they may point to the same file
Source path is missingPython raises FileNotFoundErrorCheck the source path and spelling
Destination cannot be writtenAn OSError, often PermissionError, reports the failed operationCheck that the parent directory exists and the current process can write there
Directory destination already exists in copytree()FileExistsError is raised by defaultUse dirs_exist_ok=True (Python 3.8+) only when merging and replacing same-name files is intended
Copying through copyfileobj()The destination stream is not flushed automaticallyFlush or close it before reading its copied data

For batch renames, derive each target path from its source name before copying. The AskPython shutil reference and os module guide explain related file and path operations.

Conclusion: choose the shutil method by its job

These methods cover ordinary files, streams, and directory trees without shell-specific commands, and the Python shutil reference documents platform-specific metadata and symlink behavior.

FAQ

These answers cover destination paths and the source file after a copy.

Does shutil.copy keep the original file?

Yes. shutil.copy writes a separate destination and leaves the source file in place. A later copy can overwrite an existing destination.

How do I copy a file to another directory in Python?

Call shutil.copy(source_path, destination_directory). If the destination is a directory, copy() uses the source filename there.

What is the difference between shutil.copy() and copy2()?

Both copy contents and permission mode. copy2() also attempts to preserve additional metadata such as timestamps, subject to platform limits.

Can shutil.copy() copy a CSV or text file?

Yes. shutil.copy() copies file data without parsing it, so it works for CSV and text files as well as other ordinary files.

Aditya Gupta
Aditya Gupta
Articles: 21