Of course! Moving a folder in Python is a common task. The best and most modern way to do this is by using the shutil module, which is part of Python's standard library.

Here’s a complete guide, from the simplest method to more advanced scenarios.
The Best Method: Using shutil.move()
The shutil.move() function is designed specifically for this. It's powerful because it handles both files and folders and works across different drives on Windows.
Key Features of shutil.move():
- Handles Folders: It can move an entire folder and all its contents.
- Cross-Platform: Works on Windows, macOS, and Linux.
- Smart Copy-Delete: If the source and destination are on the same filesystem, it will perform a fast "rename" operation. If they are on different drives, it will copy the folder to the destination and then delete the original.
Basic Example: Moving a Folder to a New Location
Let's say you have a folder named my_project and you want to move it from the current directory into a directory called archive.
File Structure Before:

/my_project_folder
├── main.py
└── data/
└── file.txt
/archive/
Code:
import shutil
import os
# Define the source and destination paths
# It's good practice to use os.path.join for cross-platform compatibility
source_folder = 'my_project'
destination_folder = os.path.join('archive', 'my_project_moved')
# Check if the source folder exists before moving
if os.path.exists(source_folder):
print(f"Moving '{source_folder}' to '{destination_folder}'...")
# The move function
shutil.move(source_folder, destination_folder)
print("Move complete!")
else:
print(f"Error: The source folder '{source_folder}' does not exist.")
File Structure After:
/archive/
└── my_project_moved/
├── main.py
└── data/
└── file.txt
Notice that my_project is gone from its original location and now exists inside archive.
Handling a Destination Folder with the Same Name
What happens if the destination folder already exists? This is a very common scenario.

- If the destination is a directory:
shutil.move()will merge the source folder into the destination. Any files with the same name will be overwritten. - If the destination is a file:
shutil.move()will raise anOSError.
Example: Merging Folders
Let's say you have two folders with the same name, reports, in different locations and you want to combine them.
File Structure Before:
/reports/
├── report_jan.txt
└── report_feb.txt
/archive/
└── reports/
└── report_mar.txt
Code to Merge:
import shutil
source = 'reports'
destination = 'archive/reports' # The destination already exists
print(f"Moving contents of '{source}' into '{destination}'...")
shutil.move(source, destination)
print("Merge complete!")
File Structure After:
/archive/
└── reports/
├── report_jan.txt (from original /reports)
├── report_feb.txt (from original /reports)
└── report_mar.txt (was already there)
The original /reports folder is now empty (or gone, depending on the OS's handling of empty directories after a merge).
Advanced Scenarios
A. Moving a Folder and Overwriting if it Exists
If you want to ensure the destination folder is completely replaced by the source folder, you need to manually delete the destination first.
⚠️ Warning: This will permanently delete the destination folder and all its contents.
import shutil
import os
source = 'my_project'
destination = 'archive/my_project_moved'
# Check if destination exists and delete it
if os.path.exists(destination):
print(f"Deleting existing destination folder: {destination}")
# Use shutil.rmtree for directories
shutil.rmtree(destination)
# Now, perform the move
print(f"Moving '{source}' to '{destination}'...")
shutil.move(source, destination)
print("Move and overwrite complete!")
B. Moving a Folder with Progress Bar (for large folders)
For very large folders, shutil.move() can seem to hang. You can provide feedback by using copytree with a callback and then deleting the source.
import shutil
import os
from tqdm import tqdm # You need to install this: pip install tqdm
def move_with_progress(src, dst):
"""Moves a folder with a progress bar."""
# Use copytree with a progress callback
def progress_callback(src_path, dst_path):
# This callback is called for each file copied
pass
# shutil.copytree doesn't have a built-in progress bar, so we'll use tqdm
# to manually track the total number of files.
total_files = sum(len(files) for _, _, files in os.walk(src))
with tqdm(total=total_files, unit='file', desc=f"Moving {os.path.basename(src)}") as pbar:
for root, dirs, files in os.walk(src):
for file in files:
s = os.path.join(root, file)
d = os.path.join(dst, os.path.relpath(s, src))
os.makedirs(os.path.dirname(d), exist_ok=True)
shutil.copy2(s, d) # copy2 preserves metadata
pbar.update(1)
# After copying everything, delete the original source
shutil.rmtree(src)
print("\nMove complete!")
# Example usage
source_folder = 'very_large_folder'
destination_folder = 'archive/very_large_folder'
if os.path.exists(source_folder):
move_with_progress(source_folder, destination_folder)
Summary: shutil.move() vs. os.rename()
You might also see os.rename() used for this purpose. Here’s a quick comparison:
| Feature | shutil.move() |
os.rename() |
|---|---|---|
| Primary Use | Moving files and folders. | Renaming files and folders. |
| Cross-Drives | Yes. Works across different filesystems. | No. Fails if source and destination are on different drives. |
| Overwrite | Merges into an existing destination folder. | Raises OSError if destination already exists. |
| Recommendation | Use this for moving. It's more robust and what you usually want. | Use only for simple renaming within the same directory/drive. |
Final Recommendation: For 99% of cases where you need to "move" a folder in Python, use shutil.move(). It's the correct, safe, and portable tool for the job.
