Skip to content

Commit 6432baa

Browse files
author
Patrick Bareiss
committed
testing
1 parent 3b9588b commit 6432baa

File tree

1 file changed

+216
-0
lines changed

1 file changed

+216
-0
lines changed

bin/rename_data.py

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Script to analyze folders recursively and rename data.yml files.
4+
5+
When a folder contains:
6+
- A data.yml file
7+
- Another yml file with a different name
8+
9+
The script will:
10+
1. Remove the other yml file first
11+
2. Rename data.yml to match the folder name (folder_name.yml)
12+
"""
13+
14+
import argparse
15+
import logging
16+
from pathlib import Path
17+
from typing import List, Tuple, Optional
18+
19+
20+
def setup_logging(verbose: bool = False) -> None:
21+
"""Setup logging configuration."""
22+
level = logging.DEBUG if verbose else logging.INFO
23+
logging.basicConfig(
24+
level=level,
25+
format='%(asctime)s - %(levelname)s - %(message)s',
26+
datefmt='%Y-%m-%d %H:%M:%S'
27+
)
28+
29+
30+
def find_yml_files(directory: Path) -> List[Path]:
31+
"""Find all yml/yaml files in a directory (not recursive)."""
32+
yml_files = []
33+
for file_path in directory.iterdir():
34+
if file_path.is_file() and file_path.suffix.lower() in ['.yml', '.yaml']:
35+
yml_files.append(file_path)
36+
return yml_files
37+
38+
39+
def analyze_directory(directory: Path) -> Optional[Tuple[Path, List[Path]]]:
40+
"""
41+
Analyze a directory for data.yml and other yml files.
42+
43+
Returns:
44+
Tuple of (data_yml_path, other_yml_files) if conditions are met, None otherwise
45+
"""
46+
yml_files = find_yml_files(directory)
47+
48+
if len(yml_files) < 2:
49+
return None
50+
51+
data_yml = None
52+
other_yml_files = []
53+
54+
for yml_file in yml_files:
55+
if yml_file.name.lower() == 'data.yml':
56+
data_yml = yml_file
57+
else:
58+
other_yml_files.append(yml_file)
59+
60+
# Return only if we have data.yml and at least one other yml file
61+
if data_yml and other_yml_files:
62+
return (data_yml, other_yml_files)
63+
64+
return None
65+
66+
67+
def process_directory(directory: Path, dry_run: bool = False) -> bool:
68+
"""
69+
Process a directory that meets our criteria.
70+
71+
Args:
72+
directory: The directory to process
73+
dry_run: If True, only log what would be done without actually doing it
74+
75+
Returns:
76+
True if processing was successful, False otherwise
77+
"""
78+
logger = logging.getLogger(__name__)
79+
80+
result = analyze_directory(directory)
81+
if not result:
82+
return False
83+
84+
data_yml, other_yml_files = result
85+
folder_name = directory.name
86+
new_yml_name = f"{folder_name}.yml"
87+
new_yml_path = directory / new_yml_name
88+
89+
logger.info(f"Processing directory: {directory}")
90+
logger.info(f"Found data.yml: {data_yml}")
91+
logger.info(f"Found other yml files: {[str(f) for f in other_yml_files]}")
92+
93+
try:
94+
# Step 1: Remove other yml files
95+
for other_yml in other_yml_files:
96+
if dry_run:
97+
logger.info(f"[DRY RUN] Would remove: {other_yml}")
98+
else:
99+
logger.info(f"Removing: {other_yml}")
100+
other_yml.unlink()
101+
102+
# Step 2: Rename data.yml to folder name
103+
if dry_run:
104+
logger.info(f"[DRY RUN] Would rename {data_yml} to {new_yml_path}")
105+
else:
106+
logger.info(f"Renaming {data_yml} to {new_yml_path}")
107+
data_yml.rename(new_yml_path)
108+
109+
logger.info(f"Successfully processed directory: {directory}")
110+
return True
111+
112+
except Exception as e:
113+
logger.error(f"Error processing directory {directory}: {e}")
114+
return False
115+
116+
117+
def scan_directory_recursive(root_directory: Path, dry_run: bool = False) -> \
118+
Tuple[int, int]:
119+
"""
120+
Recursively scan directories and process them.
121+
122+
Returns:
123+
Tuple of (directories_processed, errors_encountered)
124+
"""
125+
logger = logging.getLogger(__name__)
126+
processed_count = 0
127+
error_count = 0
128+
129+
logger.info(f"Starting recursive scan of: {root_directory}")
130+
131+
# Walk through all directories recursively
132+
for current_dir in root_directory.rglob('*'):
133+
if current_dir.is_dir():
134+
logger.debug(f"Checking directory: {current_dir}")
135+
136+
try:
137+
if process_directory(current_dir, dry_run):
138+
processed_count += 1
139+
except Exception as e:
140+
logger.error(f"Unexpected error processing {current_dir}: {e}")
141+
error_count += 1
142+
143+
return processed_count, error_count
144+
145+
146+
def main():
147+
"""Main function to handle command line arguments and execute the script."""
148+
parser = argparse.ArgumentParser(
149+
description="Recursively analyze folders and rename data.yml files",
150+
formatter_class=argparse.RawDescriptionHelpFormatter,
151+
epilog="""
152+
Examples:
153+
python rename_data.py /path/to/folder
154+
python rename_data.py /path/to/folder --dry-run
155+
python rename_data.py /path/to/folder --verbose
156+
"""
157+
)
158+
parser.add_argument(
159+
'folder',
160+
type=str,
161+
help='Path to the root folder to analyze'
162+
)
163+
164+
parser.add_argument(
165+
'--dry-run',
166+
action='store_true',
167+
help='Show what would be done without actually making changes'
168+
)
169+
170+
parser.add_argument(
171+
'--verbose',
172+
action='store_true',
173+
help='Enable verbose logging'
174+
)
175+
176+
args = parser.parse_args()
177+
178+
# Setup logging
179+
setup_logging(args.verbose)
180+
logger = logging.getLogger(__name__)
181+
182+
# Validate input folder
183+
root_path = Path(args.folder).resolve()
184+
if not root_path.exists():
185+
logger.error(f"Error: The specified folder does not exist: {root_path}")
186+
return 1
187+
188+
if not root_path.is_dir():
189+
logger.error(f"Error: The specified path is not a directory: {root_path}")
190+
return 1
191+
192+
logger.info(f"Analyzing folder: {root_path}")
193+
if args.dry_run:
194+
logger.info("DRY RUN MODE - No changes will be made")
195+
196+
# Process the directories
197+
try:
198+
processed_count, error_count = scan_directory_recursive(root_path, args.dry_run)
199+
200+
logger.info("Scan completed!")
201+
logger.info(f"Directories processed: {processed_count}")
202+
if error_count > 0:
203+
logger.warning(f"Errors encountered: {error_count}")
204+
205+
return 0 if error_count == 0 else 1
206+
207+
except KeyboardInterrupt:
208+
logger.info("Operation cancelled by user")
209+
return 1
210+
except Exception as e:
211+
logger.error(f"Unexpected error: {e}")
212+
return 1
213+
214+
215+
if __name__ == "__main__":
216+
exit(main())

0 commit comments

Comments
 (0)