140 lines · 4.2 KB
Raw Download
1
#!/usr/bin/env python3
2
import os
3
import shutil
4
import argparse
5
from pathlib import Path
6
7
8
def flatten_directory(root_path):
9
    """
10
    Move all files from subdirectories to the root directory.
11
    Delete empty subdirectories after moving files.
12
13
    Args:
14
        root_path (str or Path): Path to the root directory to flatten
15
    """
16
    root_path = Path(root_path).resolve()
17
18
    if not root_path.exists():
19
        print(f"Error: Directory '{root_path}' does not exist.")
20
        return False
21
22
    if not root_path.is_dir():
23
        print(f"Error: '{root_path}' is not a directory.")
24
        return False
25
26
    moved_files = 0
27
    deleted_dirs = 0
28
29
    # Walk through all subdirectories (bottom-up to handle nested structures)
30
    for current_dir, subdirs, files in os.walk(root_path, topdown=False):
31
        current_path = Path(current_dir)
32
33
        # Skip the root directory itself
34
        if current_path == root_path:
35
            continue
36
37
        # Move all files to the root directory
38
        for file in files:
39
            source_file = current_path / file
40
            destination_file = root_path / file
41
42
            # Handle naming conflicts by adding a number suffix
43
            counter = 1
44
            original_dest = destination_file
45
            while destination_file.exists():
46
                stem = original_dest.stem
47
                suffix = original_dest.suffix
48
                destination_file = root_path / f"{stem}_{counter}{suffix}"
49
                counter += 1
50
51
            try:
52
                shutil.move(str(source_file), str(destination_file))
53
                moved_files += 1
54
                if destination_file != original_dest:
55
                    print(
56
                        f"Moved: {source_file} → {destination_file} (renamed to avoid conflict)"
57
                    )
58
                else:
59
                    print(f"Moved: {source_file} → {destination_file}")
60
            except Exception as e:
61
                print(f"Error moving {source_file}: {e}")
62
63
        # Try to remove the directory if it's empty
64
        try:
65
            current_path.rmdir()  # Only removes if empty
66
            deleted_dirs += 1
67
            print(f"Deleted empty directory: {current_path}")
68
        except OSError:
69
            # Directory not empty (might contain subdirectories)
70
            pass
71
72
    print(f"\nOperation completed:")
73
    print(f"Files moved: {moved_files}")
74
    print(f"Empty directories deleted: {deleted_dirs}")
75
76
    return True
77
78
79
def get_directory_input():
80
    """
81
    Prompt the user for a directory path.
82
83
    Returns:
84
        str: The directory path entered by the user, or '.' if empty
85
    """
86
    while True:
87
        directory = input(
88
            "Enter the directory path to flatten (press Enter for current directory): "
89
        ).strip()
90
91
        # Use current directory if no input provided
92
        if not directory:
93
            directory = "."
94
95
        # Check if the directory exists
96
        if Path(directory).exists():
97
            if Path(directory).is_dir():
98
                return directory
99
            else:
100
                print(f"Error: '{directory}' is not a directory. Please try again.")
101
        else:
102
            print(f"Error: Directory '{directory}' does not exist. Please try again.")
103
104
105
def main():
106
    parser = argparse.ArgumentParser(
107
        description="Flatten directory structure by moving all files from subdirectories to the main folder."
108
    )
109
    parser.add_argument(
110
        "directory",
111
        nargs="?",
112
        default=None,
113
        help="Directory to flatten (default: prompt for input)",
114
    )
115
116
    args = parser.parse_args()
117
118
    # If no directory provided as argument, prompt for it
119
    if args.directory is None:
120
        directory = get_directory_input()
121
    else:
122
        directory = args.directory
123
124
    print(f"Flattening directory: {Path(directory).resolve()}")
125
    print("-" * 50)
126
127
    success = flatten_directory(directory)
128
129
    if success:
130
        print("Directory flattening completed successfully!")
131
    else:
132
        print("Directory flattening failed!")
133
        return 1
134
135
    return 0
136
137
138
if __name__ == "__main__":
139
    exit(main())
140