--- name: rename signature: 'rename OLDNAME,NEWNAME' since: 5.0 status: documented categories: ["Filehandles, files, directories"] --- ```{index} single: rename; Perl built-in ``` *[Filehandles, files, directories](../perlfunc-by-category)* # rename Change the name of a file. `rename` asks the operating system to rebind the path `OLDNAME` to `NEWNAME`. On a POSIX filesystem this is a single atomic directory operation: after the call returns successfully, `NEWNAME` refers to the file that used to be reachable as `OLDNAME`, and `OLDNAME` no longer exists. It is the same primitive the shell `mv` command reaches for when source and destination live on the same filesystem. ## Synopsis ```perl rename OLDNAME, NEWNAME ``` ## What you get back `1` on success, `0` on failure with [`$!`](../perlvar) set to the `errno` the underlying `rename(2)` syscall returned. Always check the return value — a silent failure here leaves the filesystem in a state the rest of the program does not expect: ```perl rename $tmp, $final or die "rename $tmp -> $final failed: $!"; ``` ## Atomicity and the same-filesystem rule `rename` is atomic **only when `OLDNAME` and `NEWNAME` resolve to the same filesystem**. Within that filesystem, no intermediate state is ever visible: another process reading the directory sees either the old name or the new name, never both and never neither. This is why the canonical "write a file safely" idiom writes to a temporary file in the same directory and then renames it into place: ```perl open my $fh, ">", "$path.tmp" or die "open: $!"; print $fh $data; close $fh or die "close: $!"; rename "$path.tmp", $path or die "rename: $!"; ``` Across filesystems the call fails with `EXDEV` (`"Invalid cross-device link"`) and nothing is moved. The system `mv` command papers over this by falling back to copy-then-unlink; `rename` does not. For a portable cross-device move, use `move` from `File::Copy`, which performs the copy-and-unlink fallback itself. ## Examples Rename within a directory: ```perl rename "draft.txt", "final.txt" or die "rename: $!"; ``` Atomic file replacement — write to a sibling tempfile, then rename: ```perl my $tmp = "$path.$$.tmp"; open my $fh, ">", $tmp or die "open $tmp: $!"; print $fh $content; close $fh or die "close $tmp: $!"; rename $tmp, $path or die "rename $tmp -> $path: $!"; ``` Detect the cross-device case and fall back to `File::Copy::move`: ```perl use Errno qw(EXDEV); use File::Copy qw(move); unless (rename $src, $dst) { if ($! == EXDEV) { move($src, $dst) or die "move: $!"; } else { die "rename: $!"; } } ``` Rename every `.log` in a directory to `.log.old`: ```perl for my $f (glob "*.log") { rename $f, "$f.old" or warn "rename $f: $!"; } ``` ## Edge cases - **`NEWNAME` already exists**: silently clobbered. `rename` does **not** ask, warn, or refuse. If the target is a regular file it is unlinked as part of the operation; if it is a directory the call fails with `ENOTDIR` or `EISDIR` depending on whether `OLDNAME` is a directory. To get "refuse to overwrite" semantics, test with `-e` first (and accept that the check is racy — there is no portable `renameat2(RENAME_NOREPLACE)` exposed through `rename` itself). - **Cross-filesystem (`EXDEV`)**: fails, leaves both paths intact. Use `File::Copy::move` when the destination may be on another mount. - **Open filehandles**: on Linux (and POSIX generally) renaming a file that is currently open is fine. The open filehandle keeps pointing at the same inode; subsequent reads and writes through it continue to work. New opens use the new name. - **Directories**: renaming a directory is allowed, but only when `NEWNAME` does not exist or is an empty directory. Moving a directory into a subdirectory of itself fails with `EINVAL`. - **Permissions**: `rename` needs write + execute permission on both the source and destination parent directories, not on the file itself. Failure shows up as `EACCES` or `EPERM`. - **Sticky-bit directories** (`/tmp`): if the destination parent has the sticky bit set, you must own either the source file or the destination parent; otherwise the call fails with `EPERM` even when the directory is world-writable. - **Symlinks**: `rename` operates on the link itself, never on its target. `rename "link", "other"` renames the symlink; the file it points at is untouched. - **Trailing slash on `OLDNAME`**: many kernels reject this with `ENOTDIR` when the source is not a directory. Do not rely on trailing-slash behaviour being portable. - **Same-path rename**: `rename $p, $p` succeeds and does nothing (POSIX-required behaviour) as long as `$p` exists. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`unlink`](unlink) — remove a file by name; the tear-down counterpart to creating one with `rename` into place - [`link`](link) — make an additional hard-link name for an existing file without removing the original - [`symlink`](symlink) — create a symbolic link; note that `rename` on a symlink moves the link, not its target - `File::Copy` — portable `move` and `copy` that handle the cross-filesystem (`EXDEV`) case `rename` cannot - [`$!`](../perlvar) — `errno` after a failed `rename`; compare against constants from [`Errno`](../../Errno) (`EXDEV`, `EACCES`, `ENOENT`, …)