
Originally published on 2011-11-22; fully revised and updated.
If you write Perl for build, release, or ops automation, file test operators are one of the fastest ways to make decisions in scripts. This walkthrough shows what each common operator does, how permission checks differ for real and effective IDs, and how to structure reliable file-attribute checks in automation flows.
Perl file test operators at a glance
Perl file tests are unary operators such as -e, -f, and -x. They can test a path directly or reuse the previous file status result via _ (underscore), which helps when you run several checks on the same file.
| Operator | What it checks |
|---|---|
| -e | Path exists |
| -f | Plain file |
| -d | Directory |
| -l | Symbolic link |
| -p | Named pipe |
| -S | Socket |
| -b | Block special file |
| -c | Character special file |
| -t | Filehandle is a TTY |
| -s | File size in bytes (zero means empty) |
| -z | File size is zero |
| -u | setuid bit is set |
| -g | setgid bit is set |
| -k | Sticky bit is set |
| -T | Looks like a text file (heuristic) |
| -B | Looks like a binary file (heuristic) |
| -r / -w / -x | Readable / writable / executable by effective user or group ID |
| -R / -W / -X | Readable / writable / executable by real user or group ID |
| -o | Owned by effective user ID |
| -O | Owned by real user ID |
| -A | Age in days since last access (measured from script start time) |
| -M | Age in days since last modification (measured from script start time) |
| -C | Age in days since inode/status change (measured from script start time) |
Real ID vs effective ID permission checks
One of the most important distinctions is lowercase versus uppercase permission operators. Lowercase checks effective IDs; uppercase checks real IDs.
| Operator pair | Checks against | Typical use |
|---|---|---|
| -r vs -R | Effective IDs vs real IDs | Runtime access checks, especially in privileged contexts |
| -w vs -W | Effective IDs vs real IDs | Write-safety checks before creating or updating files |
| -x vs -X | Effective IDs vs real IDs | Verifying executability of scripts or binaries |
| -o vs -O | Effective UID vs real UID ownership | Ownership-sensitive logic in wrappers or elevated scripts |
Example script: describe a path with multiple attribute checks
This example uses _ to reuse the last file status check after -e, reducing repeated path resolution for subsequent tests.
#!/usr/bin/env perl
use strict;
use warnings;
my $file = shift @ARGV or die "Usage: $0 <path>\n";
my @description;
my $size;
if (-e $file) {
push @description, 'binary' if -B _;
push @description, 'socket' if -S _;
push @description, 'text file' if -T _;
push @description, 'block special file' if -b _;
push @description, 'character special file' if -c _;
push @description, 'directory' if -d _;
push @description, 'plain file' if -f _;
push @description, 'executable' if -x _;
$size = -s _;
push @description, defined $size ? ($size ? "$size bytes" : 'empty') : 'size unknown';
print "$file is ", join(', ', @description), "\n";
} else {
print "$file does not exist\n";
}Code language: PHP (php)
perl file_attrs.pl /etc/passwd
Workflow: where file checks fit in an automation pipeline
flowchart TD
A[Input path from script argument] --> B[Test existence with -e]
B --> C{Path exists}
C -- no --> D[Exit with clear error]
C -- yes --> E[Run type and permission tests]
E --> F[Reuse cached stat result with underscore]
F --> G[Build classification and size output]
G --> H[Decide next automation step]
Practical pattern for deployment scripts
For release automation, gate file operations on existence, readability, and non-zero size before continuing:
if (-f $artifact && -r _ && -s _) {
print "Artifact is present and readable\n";
# continue deployment
} else {
die "Artifact missing, unreadable, or empty\n";
}Code language: PHP (php)
Common pitfalls and best practices
- Prefer Perl file tests over parsing
ls -loutput in shell commands. - Be explicit about real versus effective ID checks when scripts may run with elevated privileges.
- Remember that
-Tand-Bare heuristic, not strict MIME detection. - Use underscore caching (
_) when checking many attributes on the same path. - Treat permissions and special-bit checks as platform-sensitive, especially outside Unix-like systems.
Original article: How to Check File Attributes in Perl.
I’m Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms.
I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.
Find Trusted Cardiac Hospitals
Compare heart hospitals by city and services — all in one place.
Explore Hospitals