using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text.RegularExpressions; using Newtonsoft.Json; class EpisodeRenamer { private class PatternConfig { public string Regex { get; set; } public int? Start { get; set; } public int? End { get; set; } public bool IgnoreCase { get; set; } } private class Config { public List Patterns { get; set; } public List Extensions { get; set; } } private static List patterns; private static HashSet extensions; private class Pattern { public Regex Regex { get; } public int? Start { get; } public int? End { get; } public Pattern(Regex regex, int? start, int? end) { Regex = regex; Start = start; End = end; } } static void Main() { Console.Title = Assembly.GetExecutingAssembly().GetCustomAttribute().Title; try { LoadConfiguration(); } catch (Exception ex) { Console.WriteLine($"Ошибка загрузки конфигурации: {ex.Message}"); Console.WriteLine("Программа будет завершена."); Console.ReadLine(); return; } Console.CancelKeyPress += (sender, e) => { Console.WriteLine("\nВыход из программы."); Environment.Exit(0); }; Console.WriteLine("Чтобы оставить текущую директорию нажмите 'Enter'"); Console.WriteLine("Чтобы выйти нажмите 'Ctrl + C'"); while (true) { try { Console.Write("\nВведите путь до папки с эпизодами: "); string input = Console.ReadLine().Trim() ?? string.Empty; string folder = string.IsNullOrEmpty(input) ? Directory.GetCurrentDirectory() : Path.GetFullPath(input); if (Directory.Exists(folder)) { ProcessFolder(folder); } else { Console.WriteLine("Указанная папка не существует."); } } catch (Exception ex) { Console.WriteLine($"Ошибка: {ex.Message}"); } } } private static void LoadConfiguration() { string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.json"); if (!File.Exists(configPath)) { throw new FileNotFoundException("Конфигурационный файл config.json не найден"); } string json = File.ReadAllText(configPath); Config config = JsonConvert.DeserializeObject(json); // Загружаем расширения файлов extensions = new HashSet(config.Extensions, StringComparer.OrdinalIgnoreCase); // Загружаем паттерны patterns = new List(); foreach (PatternConfig patternConfig in config.Patterns) { RegexOptions options = patternConfig.IgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None; Regex regex = new Regex(patternConfig.Regex, options); patterns.Add(new Pattern(regex, patternConfig.Start, patternConfig.End)); } Console.WriteLine("Конфигурация успешно загружена."); Console.WriteLine($"Загружено {patterns.Count} паттернов и {extensions.Count} расширений."); } private static void ProcessFolder(string folder) { foreach (string filePath in Directory.GetFiles(folder)) { string fileName = Path.GetFileName(filePath); string extension = Path.GetExtension(fileName); if (extensions.Contains(extension)) { RenameFile(filePath, fileName, folder); } } } private static void RenameFile(string filePath, string fileName, string folder) { string nameWithoutExt = Path.GetFileNameWithoutExtension(fileName); foreach (var pattern in patterns) { Match match = pattern.Regex.Match(nameWithoutExt); if (!match.Success) continue; string found = match.Value; int startIndex = AdjustIndex(pattern.Start, found.Length); int endIndex = AdjustIndex(pattern.End, found.Length); if (startIndex < 0 || endIndex < 0 || startIndex >= endIndex) continue; string numberStr = found.Substring( startIndex, endIndex - startIndex ); if (int.TryParse(numberStr, out int episode)) { string newName = $"{episode:D2}{Path.GetExtension(fileName)}"; string newPath = Path.Combine(folder, newName); if (!File.Exists(newPath)) { File.Move(filePath, newPath); Console.WriteLine($"\"{fileName}\" успешно переименован в \"{newName}\"."); return; } Console.WriteLine($"Ошибка: файл \"{newName}\" уже существует."); } } } private static int AdjustIndex(int? index, int length) { if (!index.HasValue) return length; if (index.Value < 0) return length + index.Value; return index.Value; } }