1. Introdução
Existem muitos cenários onde operações de mover são necessárias: mover arquivos "baixados" da pasta temporária para a pasta de documentos, organizar um grande volume de fotos, renomear por padrão, processar emails e logs. O sistema de arquivos gosta de ordem — ou pelo menos de algo parecido! E um bom desenvolvedor precisa saber como colocar essa ordem.
Além disso, essas tarefas frequentemente aparecem em entrevistas: "Escreva uma utilidade que renomeie todos os arquivos adicionando um número de versão", ou "Faça um comando que mova documentos obsoletos para um arquivo". Vamos ver como fazer isso em C#.
Visão geral das possibilidades
No .NET existem duas formas principais de mover e renomear — usar métodos estáticos (File.Move, Directory.Move) ou métodos de instância (FileInfo.MoveTo, DirectoryInfo.MoveTo). Todos esses métodos, por baixo dos panos, fazem quase a mesma coisa — a diferença é principalmente na sintaxe.
Como o .NET "vê" mover e renomear?
Atenção! Renomear e mover — essencialmente a mesma operação: um arquivo ou pasta em locais diferentes do sistema de arquivos é identificado pelo seu caminho. Se o caminho muda — considera-se que o objeto foi "movido" ou "renomeado". Se você muda apenas o nome, mantendo o mesmo diretório — isso é renomear. Se muda o caminho todo — é mover. Filosofia meio Schrödinger: o objeto está tanto movido quanto renomeado se você apontar um novo caminho com um novo nome!
2. Movendo e renomeando arquivos: exemplos
Vamos do simples para o complexo e continuar baseado no nosso mini-gerenciador de arquivos.
Método estático File.Move
Aqui vai um exemplo de como mover (ou renomear) um arquivo:
// Movemos o arquivo test1.txt para outra pasta com novo nome
File.Move(@"C:\Temp\test1.txt", @"C:\Archive\test1_archived.txt");
E se quiser só renomear o arquivo na mesma pasta:
// Apenas trocamos o nome do arquivo
File.Move(@"C:\Temp\test1.txt", @"C:\Temp\test_renamed.txt");
Isso é toda a mágica! O .NET basicamente "corta" um caminho e "atribui" outro ao objeto, se ambos os caminhos estiverem disponíveis e não houver conflitos.
Método estático Directory.Move
Com pastas — é análogo:
// Movemos a pasta
Directory.Move(@"C:\Temp\OldFolder", @"C:\Temp\NewFolder");
Você pode tanto renomear a pasta (novo nome no mesmo diretório) quanto movê-la inteiramente para outro lugar.
3. Métodos de instância: FileInfo.MoveTo e DirectoryInfo.MoveTo
Quando você já tem um objeto FileInfo ou DirectoryInfo, pode chamar o método MoveTo():
var fileInfo = new FileInfo(@"C:\Temp\test1.txt");
fileInfo.MoveTo(@"C:\Archive\test1_archived.txt");
// Pastas:
var dirInfo = new DirectoryInfo(@"C:\Temp\OldFolder");
dirInfo.MoveTo(@"C:\Temp\NewFolder");
Aqui também: se o novo caminho for o mesmo diretório com outro nome, ocorre renomeação; se for outro diretório — movimento.
4. E se o arquivo já existir no destino?
Aí começam os detalhes que adoram "morder" no pior momento.
File.Move
Se já existir um arquivo no caminho destino especificado — será lançada a exceção IOException, e seu código "vai cair":
try
{
File.Move("data.txt", "archive\\data.txt");
}
catch (IOException ex)
{
Console.WriteLine("Arquivo de destino já existe! " + ex.Message);
}
FileInfo.MoveTo
Mesma história — IOException se o arquivo de destino já existir.
Directory.Move
Com pastas a situação é ainda mais rígida: se a pasta de destino já existe — exceção. Você não pode mover uma pasta para um local que já está ocupado.
Moral: Sempre verifique se já não existe esse arquivo ou pasta onde você quer gravar!
// Verificamos com calma se há arquivo no caminho de destino
if (!File.Exists("archive\\data.txt"))
{
File.Move("data.txt", "archive\\data.txt");
}
else
{
Console.WriteLine("Arquivo de destino já existe!");
}
5. Dicas úteis
Exemplo de renomear uma pasta
var oldDir = @"C:\Projects\OldReport";
var newDir = @"C:\Projects\NewReport";
// Verificamos se a pasta nova não existe e se a antiga existe
if (Directory.Exists(oldDir) && !Directory.Exists(newDir))
{
Directory.Move(oldDir, newDir);
Console.WriteLine("Pasta renomeada com sucesso.");
}
else
{
Console.WriteLine("Erro: pasta de origem não encontrada ou a nova já existe.");
}
Renomear considerando conteúdo aninhado
Todo o conteúdo da pasta (subpastas, arquivos) será movido junto sem comandos adicionais! Isso é conveniente: num único comando a pasta com qualquer profundidade fica no novo local.
Boas práticas e métodos úteis da classe Path
Ao renomear ou mover arquivos, use os métodos da classe System.IO.Path para montar corretamente o novo caminho ou alterar o nome do arquivo:
- Obter o nome do arquivo sem extensão: Path.GetFileNameWithoutExtension(path)
- Trocar apenas a extensão: Path.ChangeExtension(path, ".bak")
- Construir um novo caminho com outro nome: 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. Nuances importantes e erros típicos
Permissões e bloqueio
Se você não tem permissão de escrita em um dos caminhos — será lançada a exceção UnauthorizedAccessException. Do mesmo modo, se o arquivo estiver sendo usado por outro processo (por exemplo, aberto no Word), você receberá um erro. Isso é bem comum.
Mover entre discos e volumes diferentes
Na prática, File.Move implementa uma operação rápida de renomear dentro de um mesmo volume/disco. Se você tentar mover um arquivo do disco C para o disco D — o .NET automaticamente fará uma cópia seguida da exclusão do arquivo original. Se algo der errado (por exemplo, o disco de destino ficar cheio), o arquivo original permanecerá no lugar.
Fato interessante: quase todos os sistemas de arquivos modernos suportam "rename/move" rápido dentro do volume, e ao mover entre volumes — ocorre copy + delete.
Mover pastas inteiras (Directory.Move)
Não é possível mover uma pasta para dentro de si mesma ou para uma subpasta dela (por exemplo, C:\Data para C:\Data\Archive) — isso causará erro.
Como mover com segurança?
Antes de qualquer movimento, especialmente em massa, verifique a existência da origem (File.Exists, Directory.Exists) e a ausência de conflito no destino. E não esqueça do try-catch: o sistema de arquivos é caprichoso, pode lançar erro no momento mais inesperado.
GO TO FULL VERSION