1. Вступ
Сценаріїв, коли потрібні операції переміщення, — сила-силенна: перенесення «завантажених» файлів із тимчасового каталогу до каталогу документів, масове впорядкування фотографій, перейменування за шаблоном, розбір пошти та логів. Файлова система любить порядок — або принаймні його подобу. А хороший розробник має вміти цей порядок наводити.
До того ж ці завдання часто дають на співбесідах: «Напишіть утиліту, яка перейменує всі файли, додавши до них номер версії», або «Зробіть команду, що переміщує застарілі документи в архів». Розберімося, як це робиться у C#.
Огляд можливостей
У .NET є два основні способи переміщення й перейменування: використовувати статичні методи (File.Move, Directory.Move) або екземплярні методи (FileInfo.MoveTo, DirectoryInfo.MoveTo). Усі ці методи внутрішньо виконують ту саму операцію; відрізняється здебільшого синтаксис.
Як .NET «бачить» переміщення й перейменування?
Увага! Перейменування й переміщення — по суті одна операція: файл або каталог у файловій системі визначається своїм шляхом. Якщо шлях змінюється — вважається, що об’єкт «перемістився» або «перейменувався». Якщо ви змінюєте лише ім’я, лишаючи той самий каталог — це перейменування. Якщо змінюєте шлях цілком — це переміщення. Майже як у Шредінґера: об’єкт і переміщений, і перейменований, якщо вказати новий шлях із новим ім’ям!
2. Переміщення й перейменування файлів: приклади
Рухатимемося від простого до складного і продовжимо на базі нашого мініфайлового менеджера.
Статичний метод File.Move
Ось приклад, як перемістити (або перейменувати) файл:
// Переміщуємо файл test1.txt до іншого каталогу з новим іменем
File.Move(@"C:\Temp\test1.txt", @"C:\Archive\test1_archived.txt");
А якщо потрібно просто перейменувати файл у тому самому каталозі:
// Просто змінюємо ім’я файла
File.Move(@"C:\Temp\test1.txt", @"C:\Temp\test_renamed.txt");
Власне, це й усе. .NET просто змінює шлях об’єкта, якщо обидва шляхи доступні й немає конфліктів.
Статичний метод Directory.Move
З каталогами — аналогічно:
// Переміщуємо каталог
Directory.Move(@"C:\Temp\OldFolder", @"C:\Temp\NewFolder");
Можна як перейменувати каталог (нове ім’я в тому самому каталозі), так і перемістити його цілком в інше місце.
3. Екземплярні методи: FileInfo.MoveTo і DirectoryInfo.MoveTo
Коли у вас уже є об’єкт FileInfo або DirectoryInfo, можна викликати метод MoveTo():
var fileInfo = new FileInfo(@"C:\Temp\test1.txt");
fileInfo.MoveTo(@"C:\Archive\test1_archived.txt");
// Каталоги:
var dirInfo = new DirectoryInfo(@"C:\Temp\OldFolder");
dirInfo.MoveTo(@"C:\Temp\NewFolder");
Тут так само: якщо новий шлях — це той самий каталог, але з іншим ім’ям, відбувається перейменування; якщо інший каталог — переміщення.
4. А що, якщо файл уже існує в місці призначення?
Саме тут з’являються нюанси, що часто виявляються у найневідповідніший момент.
File.Move
Якщо за вказаним шляхом призначення файл уже існує — буде згенеровано виняток IOException, і програма завершиться з помилкою:
try
{
File.Move("data.txt", "archive\\data.txt");
}
catch (IOException ex)
{
Console.WriteLine("Файл призначення вже існує! " + ex.Message);
}
FileInfo.MoveTo
Ситуація така сама — IOException, якщо файл призначення вже є.
Directory.Move
З каталогами вимоги ще суворіші: якщо цільовий каталог уже існує — виняток. Не можна перемістити каталог у каталог, який уже зайнятий.
Висновок: завжди перевіряйте, чи немає такого файла або каталогу там, куди ви намагаєтеся записати!
// Спокійно перевіряємо, чи є файл за цільовим шляхом
if (!File.Exists("archive\\data.txt"))
{
File.Move("data.txt", "archive\\data.txt");
}
else
{
Console.WriteLine("Файл призначення вже існує!");
}
5. Корисні нюанси
Приклад перейменування каталогу
var oldDir = @"C:\Projects\OldReport";
var newDir = @"C:\Projects\NewReport";
// Перевіряємо, чи немає нового каталогу і чи є старий
if (Directory.Exists(oldDir) && !Directory.Exists(newDir))
{
Directory.Move(oldDir, newDir);
Console.WriteLine("Каталог успішно перейменовано.");
}
else
{
Console.WriteLine("Помилка: вихідний каталог не знайдено або новий уже існує.");
}
Перейменування з урахуванням вкладеного вмісту
Увесь вміст каталогу (підкаталоги, файли) переміститься разом із ним без будь-яких додаткових команд. Це зручно: однією командою каталог з будь-якою вкладеністю опиняється в новому місці.
Найкращі практики та корисні методи класу Path
Коли перейменовуєте або переміщуєте файли, використовуйте методи з класу System.IO.Path, щоб коректно зібрати новий шлях або змінити ім’я файла:
- Отримати ім’я файла без розширення: Path.GetFileNameWithoutExtension(path)
- Замінити лише розширення: Path.ChangeExtension(path, ".bak")
- Побудувати новий шлях з іншим ім’ям: Path.Combine(Path.GetDirectoryName(path), "newname.txt")
string oldPath = @"C:\Reports\2023_Final.docx";
string newName = "2023_Archive.docx";
string newPath = Path.Combine(Path.GetDirectoryName(oldPath)!, newName);
File.Move(oldPath, newPath);
6. Важливі нюанси та типові помилки
Права доступу та блокування
Якщо у вас немає прав на запис за одним із шляхів — буде згенеровано виняток UnauthorizedAccessException. Аналогічно, якщо файл використовується іншим процесом (наприклад, відкритий у Word), отримаєте помилку. Це дуже поширений випадок.
Переміщення між різними дисками і томами
По суті, File.Move реалізує швидку операцію перейменування всередині одного тому/диска. Якщо спробуєте перемістити файл з диска C на диск D — .NET автоматично виконає копіювання з подальшим видаленням вихідного файла. Якщо щось піде не так (наприклад, диск призначення заповнений), вихідний файл залишиться на місці.
Цікавий факт: майже всі сучасні файлові системи підтримують «швидке перейменування/переміщення» всередині тому, а під час переміщення між томами — копіювання + видалення.
Переміщення цілих каталогів (Directory.Move)
Не можна перемістити каталог усередину самого себе або у вкладений у нього каталог (наприклад, C:\Data у C:\Data\Archive) — це спричинить помилку.
Як безпечно переміщати?
Перед будь-яким переміщенням, особливо масовим, перевіряйте існування джерела (File.Exists, Directory.Exists) і відсутність конфлікту в місці призначення. І не забувайте про try-catch: файлова система непередбачувана й може видати помилку в найнесподіваніший момент.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ