--- name: utime signature: 'utime ATIME, MTIME, LIST' since: 5.0 status: documented categories: ["Filehandles, files, directories"] --- ```{index} single: utime; Perl built-in ``` *[Filehandles, files, directories](../perlfunc-by-category)* # utime Set access and modification times on a list of files. `utime` applies the numeric access time `ATIME` and modification time `MTIME` — both Unix epoch seconds — to every file named in `LIST`. It is the Perl-level interface to the `utime(2)` and `utimes(2)` system calls, and the tool behind the Unix `touch(1)` command. The inode change time (`ctime`) of each file is set to the current time as a side effect — this is a kernel invariant, not a Perl choice, and cannot be suppressed. ## Synopsis ```perl utime ATIME, MTIME, LIST utime undef, undef, LIST # set both to "now" (since 5.8.0) ``` ## What you get back The number of files whose timestamps were successfully updated. Any file that could not be touched is silently skipped in the count; [`$!`](../perlvar) reflects the error from the *last* failing file only. Check the return value against `scalar @files` when you need to detect partial failure: ```perl my @files = ("a", "b", "c"); my $n = utime $atime, $mtime, @files; warn "only $n of ", scalar @files, " files updated: $!" if $n != @files; ``` ## Arguments - `ATIME` — new access time, in seconds since the Unix epoch. Must be numeric; non-numeric scalars are coerced the usual way and a string like `"now"` becomes `0` (midnight 1970-01-01). - `MTIME` — new modification time, same format. - `LIST` — one or more filenames. On systems that support `futimes(2)` (Linux does), filehandles may appear in `LIST` as well. Filehandles must be passed as globs (`*FH`) or glob references (`\*FH`); a bareword in that position is parsed as a filename, not a handle. ## The `undef, undef` form Since Perl 5.8.0, passing [`undef`](undef) for both `ATIME` and `MTIME` calls `utime(2)` with a null second argument. The kernel then sets both times to the current wall-clock time, and — crucially — this form succeeds on files the caller does not own, provided the caller has **write permission** on the file. The owner-or-root requirement only applies to the explicit-timestamp form. ```perl for my $file (@ARGV) { utime undef, undef, $file or warn "Couldn't touch $file: $!"; } ``` This is the form the real `touch(1)` command uses internally, and is the right choice for a generic "touch" script. ## Permissions Two distinct rules, depending on which form you use: | Form | Who may succeed | |------------------------------|-------------------------------------------------| | `utime $atime, $mtime, ...` | File owner, or root | | `utime undef, undef, ...` | Anyone with write permission on the file | A non-owner attempting the explicit-timestamp form gets `EPERM` in [`$!`](../perlvar) and the file is left untouched (it still counts as a failure, not a silent no-op). ## Examples Plain Unix-style `touch` on a list of files you own: ```perl my $now = time; utime $now, $now, @ARGV; ``` Generic `touch` that also works on files you merely have write access to: ```perl for my $file (@ARGV) { utime undef, undef, $file or warn "Couldn't touch $file: $!"; } ``` Copy timestamps from one file to another using [`stat`](stat): ```perl my @st = stat $src or die "stat $src: $!"; utime $st[8], $st[9], $dst or die "utime $dst: $!"; ``` Touch an already-open filehandle on Linux (needs `futimes(2)`): ```perl open my $fh, ">>", "log" or die $!; utime undef, undef, *$fh; # glob deref, not bareword ``` Set a file one hour into the past, useful for build-system tests: ```perl my $t = time - 3600; utime $t, $t, "stale.tmp"; ``` ## Edge cases - **Mixed `undef` and number**: passing `undef` for only one of the first two arguments does **not** trigger the "both-undef" path. The `undef` is coerced to `0` (epoch midnight 1970-01-01), the other value is used verbatim, and an `uninitialized` warning fires under `use warnings`. This is almost never what you want. ```perl use warnings; utime undef, time, $file; # atime = 1970-01-01, warning ``` - **Non-numeric timestamps**: `ATIME` and `MTIME` must be numeric. String values are coerced — `"1700000000"` works; `"yesterday"` silently becomes `0`. - **`ctime` always moves**: there is no way to preserve a file's inode change time across a `utime` call. If you need that, you need filesystem-level tools or a snapshot, not Perl. - **Filehandle in `LIST`**: must be a glob (`*FH`) or glob reference (`\*FH`). A bareword like `FH` in that position is parsed as the filename `"FH"`, and a string scalar holding a handle name is likewise treated as a filename. - **Non-existent file**: counts as a failure and does not increment the return value; [`$!`](../perlvar) is set to `ENOENT` (`No such file or directory`). - **Partial failure**: the count reflects successes only. To know *which* file failed, loop over the list one at a time. - **NFS clock skew**: the server's clock is authoritative, not the client's. A noticeable difference between the two shows up as timestamps that do not match what [`time`](time) on the client returned. - **Sub-second precision**: Perl's `utime` operates on whole seconds. Filesystems and kernels that support nanosecond timestamps will see the fractional component zeroed. Reach for `Time::HiRes::utime` (XS) if you need better resolution. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`stat`](stat) — read the timestamps `utime` writes; elements 8 (`atime`), 9 (`mtime`), and 10 (`ctime`) of the returned list - [`time`](time) — current epoch seconds, the usual source for both `ATIME` and `MTIME` - [`open`](open) and [`close`](close) — filehandles that `utime` can touch on systems with `futimes(2)` - [`$!`](../perlvar) — system error from the last failing file when the return count is less than `scalar @files` - `utime(2)`, `utimes(2)`, `futimes(2)` — the underlying system calls