fileperms()
The fileperms() function is a built-in PHP function that returns the permissions of a file. This function returns the permissions as an integer, which
PHP's fileperms() function reads the permission and type bits of a file from the filesystem and returns them as a single integer (the Unix file mode). This page covers what that integer actually contains, how to convert it into the familiar octal form like 0644, the gotcha that trips up nearly everyone the first time, and how to turn it into an ls -l-style string. On non-Unix systems such as Windows the value is less meaningful, but the function still works.
What is the fileperms() Function?
The fileperms() function returns the permissions of the file given by filename as an integer, or false on failure (for example, if the file does not exist). The integer encodes both the file type (regular file, directory, symbolic link, etc.) and the access bits (read/write/execute for owner, group, and others).
Syntax
fileperms(string $filename): int|false$filename— path to the file or directory to inspect.
Because the result is a raw integer, you almost always convert it to octal with sprintf() before showing it to a human:
sprintf('%o', fileperms($filename));The gotcha: the value is not just 0644
The number one surprise is that fileperms() does not return 0644. It returns the full mode, which includes the file-type bits. A regular file with 0644 permissions reports the octal mode 100644, and a directory with 0755 reports 40755:
<?php
$filename = 'demo.txt';
file_put_contents($filename, 'demo');
chmod($filename, 0644);
$perms = fileperms($filename);
echo $perms, "\n"; // 33188 (decimal)
echo sprintf('%o', $perms), "\n"; // 100644 (octal, includes type bits)
echo sprintf('%o', $perms & 0777), "\n"; // 644 (permission bits only)
echo substr(sprintf('%o', $perms), -4); // 0644 (last four octal digits)To get just the permission bits, mask the value with & 0777 (which drops everything above the bottom three octal digits), or take the last digits of the octal string with substr(). Use the masking approach when you want to compare against a number; use substr() when you want a printable string padded to four digits.
Reading the permissions of an existing file
In real code, check that the file exists first so you do not trigger a warning when it is missing:
<?php
$filename = 'demo.txt';
file_put_contents($filename, 'demo');
chmod($filename, 0644);
if (file_exists($filename)) {
$perms = fileperms($filename);
printf("%s -> %s\n", $filename, substr(sprintf('%o', $perms), -4));
// demo.txt -> 0644
} else {
echo "File not found.\n";
}See file_exists() for testing existence and is_readable() when you care about whether your process can actually read the file rather than the raw mode.
Turning the mode into an ls -l string
The bits returned by fileperms() map directly onto the -rw-r--r-- notation printed by ls -l. The high bits select the type character; the low nine bits are the rwx triplets for owner, group, and other. This snippet (adapted from the official PHP manual) builds that string:
<?php
$filename = 'demo.txt';
file_put_contents($filename, 'demo');
chmod($filename, 0644);
$perms = fileperms($filename);
switch ($perms & 0xF000) {
case 0xC000: $info = 's'; break; // socket
case 0xA000: $info = 'l'; break; // symbolic link
case 0x8000: $info = '-'; break; // regular file
case 0x6000: $info = 'b'; break; // block special
case 0x4000: $info = 'd'; break; // directory
case 0x2000: $info = 'c'; break; // character special
case 0x1000: $info = 'p'; break; // FIFO pipe
default: $info = 'u'; // unknown
}
// Owner
$info .= ($perms & 0x0100) ? 'r' : '-';
$info .= ($perms & 0x0080) ? 'w' : '-';
$info .= ($perms & 0x0040)
? (($perms & 0x0800) ? 's' : 'x')
: (($perms & 0x0800) ? 'S' : '-');
// Group
$info .= ($perms & 0x0020) ? 'r' : '-';
$info .= ($perms & 0x0010) ? 'w' : '-';
$info .= ($perms & 0x0008)
? (($perms & 0x0400) ? 's' : 'x')
: (($perms & 0x0400) ? 'S' : '-');
// Other
$info .= ($perms & 0x0004) ? 'r' : '-';
$info .= ($perms & 0x0002) ? 'w' : '-';
$info .= ($perms & 0x0001)
? (($perms & 0x0200) ? 't' : 'x')
: (($perms & 0x0200) ? 'T' : '-');
echo $info; // -rw-r--r--When would I use it?
- Auditing — log or report the permissions of upload directories, config files, or cache folders.
- Diagnostics — confirm a deployment script set
0755/0644correctly instead of guessing. - Conditional fixes — read the current mode, and if it is too permissive, tighten it with
chmod().
Gotchas and tips
- Always mask with
& 0777(or slice the string) before comparing to a literal like0644— otherwise the type bits make every comparison fail. - Results are cached. PHP caches stat data, so if you change permissions and re-read them in the same request, call
clearstatcache()first. - Returns
falseon error, not0. Permissions of0are technically valid, so test with===if you must distinguish a real0mode from a failure. - Windows is limited. The execute and group/other bits are not meaningful on Windows, so the value reflects only what that platform exposes.
- For the full set of file metadata (size, owner, timestamps) in one call, use
stat();filetype()returns just the type as a word likefileordir.
Conclusion
fileperms() returns the complete Unix file mode as an integer, combining the file type with the access bits. Convert it to octal with sprintf('%o', ...), remember to mask with & 0777 (or take the last digits) to isolate the permission bits, and pair it with chmod() when you need to change those permissions rather than just read them.