Crear, copiar y borrar archivos en C#

Copiar, mover y borrar son tres métodos de la clase File. Cada uno tiene una regla distinta sobre qué pasa si el destino ya existe o si el origen no está, y ahí es donde se equivoca todo el mundo.

Sin namespace, sin class Program, sin Main. Los ejemplos usan instrucciones de nivel superior, disponibles desde C# 9: el compilador genera esa estructura por ti. Y desde .NET 10 un archivo suelto se ejecuta directamente con dotnet run archivo.cs, sin crear un proyecto. El código de siempre, con su static void Main, sigue funcionando igual. Tampoco hacen falta los using System;, System.IO y compañía: los proyectos modernos los incluyen de forma implícita.

Copiar

string origen = Path.Combine("salida", "notas.txt");
string copia = Path.Combine("salida", "copia.txt");

File.Copy(origen, copia, overwrite: true);
File.Copy(origen, copia);        // otra vez, sin overwrite
salidaIOException: The file '/trabajo/salida/copia.txt' already exists.

Por omisión, Copy no pisa un archivo existente: lanza IOException. Hay que pedirlo con overwrite: true. Escribir el nombre del parámetro no es obligatorio, pero File.Copy(a, b, true) no dice nada a quien lo lea.

Mover o renombrar

File.Move(copia, nuevo);
File.Move(copia, nuevo, overwrite: true);
salidamovido: existe el viejo False, el nuevo True
Move sobre uno que existe: IOException
Move con overwrite: true -> sin error

Igual que Copy: sin overwrite no pisa. El parámetro existe desde .NET Core 3.0; en el .NET Framework antiguo había que borrar el destino antes. Renombrar es mover dentro de la misma carpeta, y está explicado con más detalle en renombrar un archivo.

Borrar

File.Delete(nuevo);
File.Delete(nuevo);              // ya no existe
salidaDelete dos veces: sin excepción la segunda
File.Delete no lanza ninguna excepción si el archivo no existe. Es lo contrario de Copy y Move, y casi todo el mundo pone un if (File.Exists(…)) delante que no hace falta. Lo que sí da error es que no exista la carpeta: DirectoryNotFoundException. Está todo en borrar un archivo.

Información del archivo

var info = new FileInfo(origen);
Console.WriteLine($"{info.Name}, {info.Length} bytes, extensión {info.Extension}, carpeta {info.Directory?.Name}");
salidaFileInfo: notas.txt, 45 bytes, extensión .txt, carpeta salida

FileInfo tiene también los métodos CopyTo, MoveTo y Delete. Es más cómodo cuando haces varias cosas con el mismo archivo; File, cuando es una operación suelta.

La versión anterior de esta página usaba rutas como C:\RutaArchivos\ o D:\dev\proyCs\, que solo existían en un ordenador. Aquí se usan rutas relativas y Path.Combine, que pone el separador correcto en cada sistema: el mismo código funciona en Windows, Linux y macOS.

Todo el código se ejecutó con .NET 10 en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.