JavaRush /Курсы /C# SELF /Перемещение файлов и директорий

Перемещение файлов и директорий

C# SELF
40 уровень , 3 лекция
Открыта

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: файловая система — дама капризная, может выдать ошибку в самый неожиданный момент.

2
Задача
C# SELF, 40 уровень, 3 лекция
Недоступна
Перемещение всех файлов из одной папки в другую
Перемещение всех файлов из одной папки в другую
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ