From c3ba2a83360e01e97448b1a100f1036c488d7b50 Mon Sep 17 00:00:00 2001 From: Lev Rusanov <30170278+JDM170@users.noreply.github.com> Date: Mon, 23 Jun 2025 21:17:26 +0700 Subject: [PATCH] Upload files Signed-off-by: Lev Rusanov <30170278+JDM170@users.noreply.github.com> --- .gitignore | 5 ++ App.config | 6 ++ Program.cs | 133 ++++++++++++++++++++++++++++ Properties/AssemblyInfo.cs | 33 +++++++ rename_anime_episodes_csharp.csproj | 53 +++++++++++ rename_anime_episodes_csharp.sln | 25 ++++++ 6 files changed, 255 insertions(+) create mode 100644 .gitignore create mode 100644 App.config create mode 100644 Program.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 rename_anime_episodes_csharp.csproj create mode 100644 rename_anime_episodes_csharp.sln diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93621e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.vs +bin/ +obj/ +packages/ +*.csproj.user diff --git a/App.config b/App.config new file mode 100644 index 0000000..193aecc --- /dev/null +++ b/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..d13da25 --- /dev/null +++ b/Program.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +class EpisodeRenamer +{ + // Паттерны для поиска номера эпизода (регулярные выражения + правила обработки) + private static readonly List patterns = new List + { + new Pattern(new Regex(@"\[\d+\]"), 1, -1), + new Pattern(new Regex(@"[s]\d+[e]\d+", RegexOptions.IgnoreCase), 4, null), + new Pattern(new Regex(@"[s]\d+[.][e]\d+", RegexOptions.IgnoreCase), 5, null), + new Pattern(new Regex(@"\d+$"), 0, null) + }; + + // Поддерживаемые расширения файлов + private static readonly HashSet extensions = new HashSet(StringComparer.OrdinalIgnoreCase) + { + ".mkv", ".avi", ".mp4" + }; + + 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.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 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; + } +} \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d20ee74 --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Общие сведения об этой сборке предоставляются следующим набором +// набора атрибутов. Измените значения этих атрибутов для изменения сведений, +// связанные с этой сборкой. +[assembly: AssemblyTitle("rename_anime_episodes_csharp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("rename_anime_episodes_csharp")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми +// для компонентов COM. Если необходимо обратиться к типу в этой сборке через +// из модели COM задайте для атрибута ComVisible этого типа значение true. +[assembly: ComVisible(false)] + +// Следующий GUID представляет идентификатор typelib, если этот проект доступен из модели COM +[assembly: Guid("aafb0ae9-6f89-4ddf-821b-1ae016fc4cfb")] + +// Сведения о версии сборки состоят из указанных ниже четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Номер редакции +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/rename_anime_episodes_csharp.csproj b/rename_anime_episodes_csharp.csproj new file mode 100644 index 0000000..81030d3 --- /dev/null +++ b/rename_anime_episodes_csharp.csproj @@ -0,0 +1,53 @@ + + + + + Debug + AnyCPU + {AAFB0AE9-6F89-4DDF-821B-1AE016FC4CFB} + Exe + rename_anime_episodes_csharp + rename_anime_episodes_csharp + v4.8 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rename_anime_episodes_csharp.sln b/rename_anime_episodes_csharp.sln new file mode 100644 index 0000000..b17f5e9 --- /dev/null +++ b/rename_anime_episodes_csharp.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35931.197 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "rename_anime_episodes_csharp", "rename_anime_episodes_csharp.csproj", "{AAFB0AE9-6F89-4DDF-821B-1AE016FC4CFB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AAFB0AE9-6F89-4DDF-821B-1AE016FC4CFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AAFB0AE9-6F89-4DDF-821B-1AE016FC4CFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AAFB0AE9-6F89-4DDF-821B-1AE016FC4CFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AAFB0AE9-6F89-4DDF-821B-1AE016FC4CFB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8CB143DF-BE22-46D5-A6A2-48E0D885DE4C} + EndGlobalSection +EndGlobal