When managing files on your computer, you may need to consolidate the contents of multiple folders into a single destination folder. This is common when organizing downloaded files, combining project assets, or restructuring directory layouts. Doing this manually is tedious and error-prone, especially when dealing with dozens of folders containing hundreds of files.
In this guide, you'll learn how to automate this process using Python's built-in os and shutil modules, handle edge cases like duplicate filenames, and build a clean, reusable solution.
Prerequisites
This guide uses only Python's built-in modules: no external packages are required:
os: for navigating directories, listing files, and creating folders.shutil: for moving files and folders between locations.
Understanding the Approach
The strategy for merging multiple folders is straightforward:
- Identify the source folders you want to merge.
- Collect the contents (files and subfolders) of each source folder.
- Create the destination folder if it doesn't already exist.
- Move all contents from each source folder into the destination.
Step-by-Step Implementation
Step 1: List Source Folders and Their Contents
First, define which folders you want to merge and gather their contents:
import os
current_folder = os.getcwd()
list_dir = ['Folder 1', 'Folder 2', 'Folder 3']
content_list = {}
for folder_name in list_dir:
folder_path = os.path.join(current_folder, folder_name)
content_list[folder_name] = os.listdir(folder_path)
for folder, files in content_list.items():
print(f"{folder}: {files}")Output (example):
Folder 1: ['File1.txt', 'File2.txt']
Folder 2: ['File3.txt', 'File4.txt']
Folder 3: ['File5.txt', 'File6.txt']Step 2: Create the Destination Folder
Create the merge destination folder if it doesn't already exist. Using os.makedirs() with exist_ok=True is the cleanest approach:
merge_folder = "merge_folder"
merge_folder_path = os.path.join(current_folder, merge_folder)
os.makedirs(merge_folder_path, exist_ok=True)
print(f"Destination folder ready: {merge_folder_path}")Step 3: Move All Contents to the Destination
Loop through each source folder and move its contents into the destination:
import shutil
for folder_name, contents in content_list.items():
for item in contents:
source_path = os.path.join(current_folder, folder_name, item)
destination_path = os.path.join(merge_folder_path, item)
shutil.move(source_path, destination_path)
print(f"Moved: {source_path} → {destination_path}")Output (example):
Moved: /home/user/Folder 1/File1.txt → /home/user/merge_folder/File1.txt
Moved: /home/user/Folder 1/File2.txt → /home/user/merge_folder/File2.txt
Moved: /home/user/Folder 2/File3.txt → /home/user/merge_folder/File3.txt
...Complete Code
Here's the full, clean implementation:
import os
import shutil
def merge_folders(source_folders, destination_folder, base_path=None):
"""
Merge the contents of multiple source folders into a single destination folder.
Args:
source_folders: List of folder names to merge.
destination_folder: Name of the destination folder.
base_path: Base directory path. Defaults to current working directory.
"""
if base_path is None:
base_path = os.getcwd()
destination_path = os.path.join(base_path, destination_folder)
os.makedirs(destination_path, exist_ok=True)
content_map = {}
for folder in source_folders:
folder_path = os.path.join(base_path, folder)
if os.path.isdir(folder_path):
content_map[folder] = os.listdir(folder_path)
else:
print(f"Warning: '{folder}' does not exist, skipping.")
moved_count = 0
for folder_name, contents in content_map.items():
for item in contents:
source = os.path.join(base_path, folder_name, item)
destination = os.path.join(destination_path, item)
shutil.move(source, destination)
moved_count += 1
print(f"Done! Moved {moved_count} items into '{destination_folder}'.")
source_folders = ['Folder 1', 'Folder 2', 'Folder 3']
destination = 'merge_folder'
merge_folders(source_folders, destination)Folder Structure Before Running
project/
├── Folder 1/
│ ├── File1.txt
│ └── File2.txt
├── Folder 2/
│ ├── File3.txt
│ └── File4.txt
├── Folder 3/
│ ├── File5.txt
│ └── File6.txt
├── Folder 4/
│ ├── File7.txt
│ └── File8.txt
└── merge_script.pyFolder Structure After Running
project/
├── Folder 1/ (empty)
├── Folder 2/ (empty)
├── Folder 3/ (empty)
├── Folder 4/ (untouched)
│ ├── File7.txt
│ └── File8.txt
├── merge_folder/
│ ├── File1.txt
│ ├── File2.txt
│ ├── File3.txt
│ ├── File4.txt
│ ├── File5.txt
│ └── File6.txt
└── merge_script.pyNotice that Folder 4 is untouched because it wasn't included in the source_folders list.
Handling Duplicate Filenames
A common issue arises when multiple source folders contain files with the same name. By default, shutil.move() will overwrite the existing file in the destination without warning.
shutil.move("Folder 1/report.txt", "merge_folder/report.txt")
shutil.move("Folder 2/report.txt", "merge_folder/report.txt") # Overwrites!To avoid data loss, rename duplicates before moving:
import os
import shutil
def safe_move(source, destination_dir):
"""
Move a file to the destination directory, renaming it if a
file with the same name already exists.
"""
filename = os.path.basename(source)
destination = os.path.join(destination_dir, filename)
if os.path.exists(destination):
name, ext = os.path.splitext(filename)
counter = 1
while os.path.exists(destination):
new_filename = f"{name}_{counter}{ext}"
destination = os.path.join(destination_dir, new_filename)
counter += 1
print(f"Renamed: '{filename}' → '{os.path.basename(destination)}'")
shutil.move(source, destination)
safe_move("Folder 1/report.txt", "merge_folder")
safe_move("Folder 2/report.txt", "merge_folder") # Saved as report_1.txtOutput:
Renamed: 'report.txt' → 'report_1.txt'Copying Instead of Moving
If you want to keep the original files in their source folders and only create copies in the destination, use shutil.copy2() instead of shutil.move():
import shutil
shutil.copy2(source_path, destination_path)Cleaning Up Empty Source Folders
After moving all files, the source folders will be empty. You can optionally remove them:
import os
source_folders = ['Folder 1', 'Folder 2', 'Folder 3']
for folder in source_folders:
folder_path = os.path.join(os.getcwd(), folder)
try:
os.rmdir(folder_path) # Only removes empty directories
print(f"Removed empty folder: {folder}")
except OSError:
print(f"Skipped '{folder}' (not empty)")Summary
| Task | Function |
|---|---|
| List folder contents | os.listdir() |
| Create destination folder | os.makedirs(path, exist_ok=True) |
| Move files | shutil.move() |
| Copy files (keep originals) | shutil.copy2() |
| Remove empty folders | os.rmdir() |
Merging multiple folders into one using Python is a straightforward process: list the source folders, collect their contents, create the destination directory, and move everything over. Always handle duplicate filenames to prevent data loss, and consider using shutil.copy2() instead of shutil.move() if you want to preserve the original files. Wrap the logic in a reusable function to keep your code clean and maintainable.