Skip to content

How to Merge Multiple Folders into One Folder Using Python

Learn how to automate merging multiple folders into a single destination folder in Python using os and shutil, including handling duplicates and preserving metadata.

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:

  1. Identify the source folders you want to merge.
  2. Collect the contents (files and subfolders) of each source folder.
  3. Create the destination folder if it doesn't already exist.
  4. 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.py

Folder 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.py

Notice 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.txt

Output:

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.

Navigation