Working with Files and Directories in Perl

File Tests

File test Meaning
-r File or directory is readable by this (effective) user or group
-w File or directory is writable by this (effective) user or group
-x File or directory is executable by this (effective) user or group
-o File or directory is owned by this (effective) user
-R File or directory is readable by this real user or group
-W File or directory is writable by this real user or group
-X File or directory is executable by this real user or group
-O File or directory is owned by this real user
-e File or directory name exists
-z File exists and has zero size (always false for directories)
-s File or directory exists and has nonzero size (the value is the size in bytes)
-f Entry is a plain file
-d Entry is a directory
-l Entry is a symbolic link
-S Entry is a socket
-p Entry is a named pipe (a “fifo”)
-b Entry is a block-special file (like a mountable disk)
-c Entry is a character-special file (like an I/O device)
-u File or directory is setuid
-g File or directory is setgid
-k File or directory has the sticky bit set
-t The filehandle is a TTY (as reported by the isatty() system function; filenames can’t be
tested by this test)
-T File looks like a “text” file
-B File looks like a “binary” file
-M Modification age (measured in days)
-A Access age (measured in days)
-C Inode-modification age (measured in days)
  • Some common ones used

-e checks for existence

die "Oops! A file called '$filename' already exists.\n"
 if -e $filename;
  • -M checks for date last modified. Example below checks if file was modified in last 28 days:
warn "Config file is looking pretty old!\n "
 if -M CONFIG > 28;
  • -S checks for disk space. The following code moves files that are large and has not been accessed in 90 days:
my @original_files = qw/ fred barney betty wilma pebbles dino bamm-bamm /;
 my @big_old_files; # The ones we want to put on backup tapes
 foreach my $filename (@original_files) {
 push @big_old_files, $filename
 if -s $filename > 100_000 and -A $filename > 90;
 }
  • Performing Multiple File tests

Multiple file tests can be done using the AND operator

Another way to reduce coding is using the _ character (underscore)

  • This can be used on the same line, or broken apart as shown below
  • Be careful as this character refers to the last referenced file. If multiple files are being referenced, need to caution which file this character is referring
  • Example:
if (-r $file and -w $file ) { ... }
 if ( -r $file and -w _ ) { ... }
 if ( -r $file ) { ... } 
 if ( -w _ ) { ... }
  • The stat and lstat function

The stat function provides all information about the file.

  • This is pretty much the same information that is kept by the operating system:
  • But this is done through a symbolic link to the file

The lstat function provides all information about the file.

  • This is same as stat except information about the actual symbolic link is also included
  • This is mostly useless…
# stat and lstat functions
 $filename = @ARGV[0];
 if (-e $filename) {
 ($dev, $ino, $mode, $nlink, $uid, $gid,

$rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($filename); 
 print "$dev, $ino, $mode, $nlink, $uid, $gid,

$rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks \n";
 # 3, 0, 33206, 1, 0, 0, 3, 107, 1254438238, 1251926568, 1254438226, ,

($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,

$atime, $mtime, $ctime, $blksize, $blocks) = lstat($filename); 
 print "$dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,

$atime, $mtime, $ctime, $blksize, $blocks \n";
 # 3, 0, 33206, 1, 0, 0, 3, 107, 1254438238, 1251926568, 1254438226, ,
 } else {
 print "invalid filename $filename \n";
 }
  • The localtime function

Timestamp, as shown in the example above, is a long list of integers and can be meaningless

Use the localtime function to convert the timestamp into human readable time

# localtime function
 $date = localtime $mtime;
 print "$mtime = $date \n";
 # 1251926568 = Wed Sep 2 14:22:48 2009

 

 

Directory Operations

  • The chdir operator

Changes the working directory

chdir "/etc" or die "cannot chdir to /etc: $!"; # $! Perl’s system level errors
  • Globbing

In Unix, typing “*.pl” in shell could result in a list of all files that end in “.pl”

Perl can do the same by globbing.

# GLOB
 @all_files = glob "*";
 foreach (@all_files) { print "$_ \n"; }

# This prints all filenames in current directoru
 # alternate way for exactly same as above
 foreach (<*>) { print "$_ \n";
  • Directory Handles

Similar to a file handler but reads file names (and other information)

# Directory Handles
$mydir = "."; # opens current directory
opendir DH, $mydir or die "Cant open directory $!";

foreach (readdir DH) { print "$_ \n"; }
closedir DH;
  • Removing Files – the unlink operator
unlink "file1.txt", "file2,txt", "file3.txt";
unlink glob "*.pl"; # deletes all perl files in this working directory
  • Renaming Files – the rename operator
rename "filename1.txt", "filename2.txt";
  • Making and Removing Directories – the mkdir and rmdir operators
mkdir "mydir", 0755 or warn "Cannot create directory $!";

rmdir "mydir";
  • Modifying Permissions
chmod 0755, "mydir", "myotherdir";
  • Changing Ownership
chown user_name, group_id, glob "*.*";
  • Changing Timestamps
runtime creation_time, modified_time, glob "*.*";
  • Links and Files

On a hard drive, every file is stored in an inode, which is a space on disk reserved for that file

A directory itself is another file, that stores all filenames with their corresponding inode values that are supposed to be contained in that directory

  • Example – if file X.txt is under the /home/bin directory, there are two inodes in play here
  • Inode 100 = x.txt and the contents of the file
  • Inode 700 = /home/bin and the contents of the directory, including x.txt filename and its corresponding 100 inode ID

All files also have link values.

  • Link of zero means no directory is pointing to it, therefore it is free space that can be overwritten
  • Deleting a file just sets it’s link value to zero
  • Link value of 1 means 1 reference to that file, therefore it exists, such as the /home/bin/x.txt example above
  • Link values can be greater than 1 if multiple links are used
  • Link “x.txt”, “y.txt” à this creates a link file “y.txt” to the exact same file “x.txt”

They point to the exact same file

Note this is not the same as copy

Symbolic Link values can also be used, which are like links but do not increment the link count

  • Symbolic links connect one file name to another, but the destination’s file link count does not increment
  • Symbolic link is used to tell a system to look elsewhere for that file