--- name: stat signature: 'stat FILEHANDLE' since: 5.0 status: documented categories: ["Filehandles, files, directories"] --- ```{index} single: stat; Perl built-in ``` *[Filehandles, files, directories](../perlfunc-by-category)* # stat Get a file's status information. `stat` asks the operating system for the metadata record of a file — size, ownership, permissions, timestamps, inode — and returns it as a 13-element list. It is the underlying primitive behind the `-X` file tests (`-e`, `-f`, `-r`, …), behind modules like `File::stat`, and behind any script that needs to inspect a file without opening it. `stat` dereferences symlinks and reports on the target; use [`lstat`](lstat) to get the link itself. ## Synopsis ```perl stat FILEHANDLE stat EXPR stat DIRHANDLE stat stat _ ``` ## What you get back In list context, a 13-element list of numeric fields. In scalar context, a boolean: true on success, false on failure. Either way, on success the kernel's stat buffer is cached in the special filehandle `_`, which any subsequent `stat`, [`lstat`](lstat), or `-X` test can re-use without a new syscall. On failure, list context returns the empty list and [`$!`](../perlvar) is set to the `errno` value from the failed `stat(2)`. The fields, in order: | Index | Field | Meaning | |-------|----------|--------------------------------------------------------------------| | 0 | `dev` | device number of the filesystem holding the file | | 1 | `ino` | inode number | | 2 | `mode` | file mode — type bits **and** permission bits combined | | 3 | `nlink` | number of hard links to the file | | 4 | `uid` | numeric user ID of the owner | | 5 | `gid` | numeric group ID of the owner | | 6 | `rdev` | device identifier, for character/block special files | | 7 | `size` | total size in bytes | | 8 | `atime` | last access time, seconds since the epoch (1970-01-01 00:00 GMT) | | 9 | `mtime` | last modify time, seconds since the epoch | | 10 | `ctime` | inode change time, seconds since the epoch — **not** creation time | | 11 | `blksize`| preferred I/O block size for reads/writes against this file | | 12 | `blocks` | number of filesystem blocks actually allocated (often 512 B each) | Field 2 (`mode`) packs both the file type and the permission bits into one number. Mask with `07777` to see just the permissions; use the `S_IF*` constants and `S_IS*` helpers from `Fcntl` to test the type portably. ```perl my $mode = (stat($filename))[2]; printf "permissions are %04o\n", $mode & 07777; ``` Not every filesystem populates every field. `atime`, `blksize`, and `blocks` may come back as `0` on filesystems that do not track them (for instance some FUSE mounts or network filesystems); `ctime` is not a portable "creation time" — it tracks the last change to the inode itself (permissions, ownership, link count), not when the file was first created. ## Global state it touches - [`$_`](../perlvar) — read when `stat` is called with no argument. `stat` with no `EXPR` stats the filename held in [`$_`](../perlvar), **not** the cached `_` handle. - [`$!`](../perlvar) — set to the `errno` of the failed `stat(2)` syscall when the call fails. - The **special `_` filehandle** — a per-interpreter cache of the most recent successful `stat`, [`lstat`](lstat), or `-X` result. Passing `_` as the argument reuses that cached buffer and issues no syscall. Successful calls refresh it; failed calls leave the previous contents in place. ## Examples Basic list-context unpack: ```perl my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($filename); ``` Pick out a single field with a list slice: ```perl my $size = (stat($filename))[7]; my $mtime = (stat($filename))[9]; ``` Scalar context as an existence-plus-readable-metadata probe: ```perl if (stat($path)) { my $size = (stat _)[7]; # reuse the cached buffer print "size = $size\n"; } else { warn "stat $path: $!"; } ``` Reusing the cache across an `-X` test and a `stat`: ```perl if (-x $file && (($d) = stat(_)) && $d < 0) { print "$file is executable NFS file\n"; } ``` Named-accessor access through `File::stat`: ```perl use File::stat; my $sb = stat($filename); printf "file %s, size %s, perm %04o, mtime %s\n", $filename, $sb->size, $sb->mode & 07777, scalar localtime $sb->mtime; ``` Decoding the mode with `Fcntl`: ```perl use Fcntl ':mode'; my $mode = (stat($filename))[2]; printf "permissions %04o\n", S_IMODE($mode); print "is a directory\n" if S_ISDIR($mode); ``` ## Edge cases - **No argument**: `stat;` stats [`$_`](../perlvar), **not** the cached `_` handle. To re-read the cache you must write `stat(_)` with the underscore as an explicit bareword. - **The `_` bareword is special**: it names the stat cache, not a file. Quoting it (`stat("_")`) stats a file literally called `_` in the current directory. - **Symlinks are followed**: `stat` reports on the target of a symlink. For the link itself, use [`lstat`](lstat). A broken symlink makes `stat` fail with `ENOENT`; [`lstat`](lstat) on the same path succeeds. - **DIRHANDLE form**: passing a directory handle from [`opendir`](opendir) returns the stat of the open directory itself. Not every platform supports this; on those that do not, the call fails and [`$!`](../perlvar) is set. - **Inode numbers may overflow integers**: on filesystems with 64-bit inode numbers beyond Perl's integer range, `ino` is returned as a decimal string to preserve the full value. Compare inode numbers with `eq`, not `==`, to stay correct on those filesystems. `eq` works fine on numeric inodes too. - **`ctime` is not creation time**: it is the inode-change time — updated by [`chmod`](chmod), [`chown`](chown), [`rename`](rename), link-count changes, and the file's own writes. Linux exposes a true creation time (`btime`) via `statx(2)`, but that is not part of `stat`'s return list. - **Zero fields on some filesystems**: `atime` (on `noatime` mounts), `blksize`, and `blocks` may be reported as `0`. Treat `0` as "unavailable", not as a meaningful value. - **Scalar context does not populate `_` on failure**: a failed `stat` leaves the previous cached buffer untouched. Always check the return value before a follow-up `stat(_)` or `-X _`. - **Race windows**: the metadata returned is a snapshot. Anything that acts on a path based on `stat`'s result (permission checks, TOCTOU patterns) must be written to tolerate the file changing between the `stat` and the follow-up operation — or better, open the file first and `stat` the filehandle. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`lstat`](lstat) — like `stat` but does **not** follow symlinks; reports on the link itself - `-X` file-test operators (`-e`, `-f`, `-r`, `-w`, `-x`, …) — built on top of the same stat buffer; share the `_` cache with `stat` and [`lstat`](lstat) - [`chmod`](chmod) — change the permission bits reported in field 2 (`mode`) - [`chown`](chown) — change the `uid` and `gid` reported in fields 4 and 5 - `File::stat` — named accessors (`$sb->size`, `$sb->mtime`, …) over the same 13-field list; `use File::stat` overrides `stat` in the current scope - `Fcntl` — `:mode` tag exports the `S_I*` constants and `S_IS*` helpers for decoding field 2