using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using AxCopilot.SDK; using AxCopilot.Services; namespace AxCopilot.Handlers; public class RenameHandler : IActionHandler { public string? Prefix => "rename"; public PluginMetadata Metadata => new PluginMetadata("Rename", "파일 일괄 이름변경 — rename", "1.0", "AX"); public Task> GetItemsAsync(string query, CancellationToken ct) { string text = query.Trim(); if (string.IsNullOrWhiteSpace(text)) { return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlyArray(new LauncherItem[3] { new LauncherItem("파일 일괄 이름변경", "rename [폴더\\패턴] [새이름 템플릿]", null, null, null, "\ue8ac"), new LauncherItem("사용 예시", "rename C:\\work\\*.xlsx 보고서_{n} → 보고서_1.xlsx, 보고서_2.xlsx ...", null, null, null, "\ue946"), new LauncherItem("변수: {n} 순번, {date} 날짜, {orig} 원본명", "rename D:\\photos\\*.jpg {date}_{n} → 2026-03-27_1.jpg ...", null, null, null, "\ue946") })); } string[] array = text.Split(' ', 2, StringSplitOptions.TrimEntries); string path = array[0]; string text2 = ((array.Length > 1) ? array[1] : null); string dir = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); if (string.IsNullOrWhiteSpace(dir) || !Directory.Exists(dir)) { return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("폴더를 찾을 수 없습니다", "경로: " + (dir ?? "(비어 있음)"), null, null, null, "\ue7ba"))); } string[] array2; try { array2 = Directory.GetFiles(dir, fileName); } catch { array2 = Array.Empty(); } if (array2.Length == 0) { return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("일치하는 파일이 없습니다", "패턴: " + fileName + " · 폴더: " + dir, null, null, null, "\ue7ba"))); } Array.Sort(array2); if (string.IsNullOrWhiteSpace(text2)) { List list = array2.Take(10).Select((string f, int i) => new LauncherItem(Path.GetFileName(f), dir, null, null, null, "\ue8a5")).ToList(); list.Insert(0, new LauncherItem($"총 {array2.Length}개 파일 발견", "뒤에 새 이름 템플릿을 추가하세요 (예: 보고서_{n})", null, null, null, "\ue946")); return Task.FromResult((IEnumerable)list); } string newValue = DateTime.Today.ToString("yyyy-MM-dd"); List<(string, string)> list2 = new List<(string, string)>(); for (int num = 0; num < array2.Length; num++) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(array2[num]); string extension = Path.GetExtension(array2[num]); string text3 = text2.Replace("{n}", (num + 1).ToString()).Replace("{date}", newValue).Replace("{orig}", fileNameWithoutExtension); if (!Path.HasExtension(text3)) { text3 += extension; } list2.Add((Path.GetFileName(array2[num]), text3)); } List list3 = new List(); list3.Add(new LauncherItem($"총 {array2.Length}개 파일 이름변경 실행", $"Enter로 실행 · {list2[0].Item1} → {list2[0].Item2} ...", null, ValueTuple.Create(dir, array2, list2.Select<(string, string), string>(((string From, string To) p) => p.To).ToArray()), null, "\ue8ac")); foreach (var (text4, text5) in list2.Take(8)) { list3.Add(new LauncherItem(text4 + " → " + text5, "미리보기", null, null, null, "\ue8a5")); } if (array2.Length > 8) { list3.Add(new LauncherItem($"... 외 {array2.Length - 8}개", "", null, null, null, "\ue946")); } return Task.FromResult((IEnumerable)list3); } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { if (!(item.Data is (string, string[], string[]) tuple) || 1 == 0) { return Task.CompletedTask; } (string, string[], string[]) tuple2 = tuple; string item2 = tuple2.Item1; string[] item3 = tuple2.Item2; string[] item4 = tuple2.Item3; int num = 0; int num2 = 0; for (int i = 0; i < item3.Length && i < item4.Length; i++) { try { string text = Path.Combine(item2, item4[i]); if (File.Exists(text)) { num2++; continue; } File.Move(item3[i], text); num++; } catch { num2++; } } string message = ((num2 > 0) ? $"{num}개 이름변경 완료, {num2}개 실패 (이미 존재하거나 접근 불가)" : $"{num}개 파일 이름변경 완료"); NotificationService.Notify("AX Copilot", message); return Task.CompletedTask; } }