Filehandles, files, directories
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#
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;
$! reflects the error from the last failing file only.
Check the return value against scalar @files when you need to
detect partial failure:
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"becomes0(midnight 1970-01-01).MTIME— new modification time, same format.LIST— one or more filenames. On systems that supportfutimes(2)(Linux does), filehandles may appear inLISTas 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 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.
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 |
|---|---|
|
File owner, or root |
|
Anyone with write permission on the file |
A non-owner attempting the explicit-timestamp form gets EPERM in
$! 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:
my $now = time;
utime $now, $now, @ARGV;
Generic touch that also works on files you merely have write
access to:
for my $file (@ARGV) {
utime undef, undef, $file
or warn "Couldn't touch $file: $!";
}
Copy timestamps from one file to another using stat:
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)):
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:
my $t = time - 3600;
utime $t, $t, "stale.tmp";
Edge cases#
Mixed
undefand number: passingundeffor only one of the first two arguments does not trigger the “both-undef” path. Theundefis coerced to0(epoch midnight 1970-01-01), the other value is used verbatim, and anuninitializedwarning fires underuse warnings. This is almost never what you want.use warnings; utime undef, time, $file; # atime = 1970-01-01, warning
Non-numeric timestamps:
ATIMEandMTIMEmust be numeric. String values are coerced —"1700000000"works;"yesterday"silently becomes0.ctimealways moves: there is no way to preserve a file’s inode change time across autimecall. 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 likeFHin 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;
$!is set toENOENT(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
timeon the client returned.Sub-second precision: Perl’s
utimeoperates on whole seconds. Filesystems and kernels that support nanosecond timestamps will see the fractional component zeroed. Reach forTime::HiRes::utime(XS) if you need better resolution.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
stat— read the timestampsutimewrites; elements 8 (atime), 9 (mtime), and 10 (ctime) of the returned listtime— current epoch seconds, the usual source for bothATIMEandMTIMEopenandclose— filehandles thatutimecan touch on systems withfutimes(2)$!— system error from the last failing file when the return count is less thanscalar @filesutime(2),utimes(2),futimes(2)— the underlying system calls