Java – Renombrar un archivo

Renombrar y mover son la misma operación: Files.move. Y conviene usarla en vez del viejo renameTo, que cuando falla se limita a devolver false.

Renombrar

import java.nio.file.*;

void main() throws Exception {
    Path viejo = Path.of("salida", "copia.txt");
    Path nuevo = Path.of("salida", "renombrado.txt");

    Files.move(viejo, nuevo, StandardCopyOption.REPLACE_EXISTING);
    IO.println("existe el viejo: " + Files.exists(viejo)
             + " | existe el nuevo: " + Files.exists(nuevo));
}
salidaexiste el viejo: false | existe el nuevo: true

Renombrar es mover dentro de la misma carpeta. Para moverlo a otra, se cambia la ruta de destino y ya está; la carpeta de destino tiene que existir, o salta NoSuchFileException.

Por qué no renameTo

File viejo = new File("archivo.txt");
File nuevo = new File("archivoNuevo.txt");

if (viejo.renameTo(nuevo)) {
    System.out.println("archivo renombrado");
} else {
    System.out.println("error");      // ¿qué error?
}
Ese else es el problema. renameTo devuelve false y no dice nada más: puede ser que el original no exista, que no tengas permiso, que el destino ya esté ocupado o que estés cruzando de disco. Con Files.move cada uno de esos casos es una excepción distinta, con la ruta dentro. Para un programa que alguien tendrá que depurar algún día, la diferencia es enorme.

Las opciones

OpciónQué hace
ningunafalla con FileAlreadyExistsException si el destino existe
REPLACE_EXISTINGpisa el destino
ATOMIC_MOVEo se hace del todo o no se hace; nadie ve un archivo a medias

ATOMIC_MOVE es el que se usa para publicar un archivo sin que nadie lo lea a medio escribir: escribes en un temporal de la misma carpeta y lo mueves encima del bueno. Dentro del mismo sistema de archivos la operación es instantánea.

Path tmp = destino.resolveSibling(destino.getFileName() + ".tmp");
Files.writeString(tmp, contenido);
Files.move(tmp, destino, StandardCopyOption.REPLACE_EXISTING,
                         StandardCopyOption.ATOMIC_MOVE);
Entre discos distintos no hay movimiento atómico. Si el origen y el destino están en sistemas de archivos diferentes —otra partición, un disco de red, un volumen de Docker—, no se puede renombrar: hay que copiar y borrar. Files.move lo hace por ti si no pides ATOMIC_MOVE; si lo pides, lanza AtomicMoveNotSupportedException.

Más información en inglés: Rename a file in Java.

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