If you are looking to write code in Perl which will work on multiple platforms then you must have the knowledge of filesystem of each platform. Filesystems are categoriesed in 3 parts.
1. Filesystem of Unix
FFS (Berkeley Fast File System) is the ancestor of all current filesystems of Unix variants. The filesystem has been extended by different vendors according to their needs. Like for better security they have been extended to provide support for POSIX ACL (access control list).
In Unix filesystem the root is denoted by / (forward slash). The path of any directory in Unix filesystem starts from / and goes deeper in the system. The directory names or file names in Unix filesystem are case-sensitive.
Path Example: /root/home/user/Desktop/file.txt
2. Filesystem of Windows
Operating systems which are based on Windows supports 3 filesystems: FAT (File Allocation Table), NTFS (NT FileSystem), FAT32 (Advance version of FAT).
FAT filesystem is not case-sensitive. It uses \\ (backward slash) as path separator. In the FAT systems the direcotries and files contains some flags, these flags are known as attributes like “Read Only”. NTFS supports unicode feature.
Path Example: C:\\home\\user\\Desktop\\file.txt
3. Filesystem of Mac OS
Classic Mac OS used HFS (Hierarchical File System). The version 8.1 of Mac OS uses HFS+ which is an advance version of HFS. The current filesystem looks similar to Unix filesystem. The method of showing paths is same in both OS. The difference between these is that Unix file system is case-sensitive whereas HFS+ is not case-sensitive.
Summary
OS and FileSystem | Path Separator | Filename length | Absolute path format | Relative path format | Unique features |
---|---|---|---|---|---|
Unix (Berkeley FFS and others) | / | OS-dependent number of chars | /dir/file | dir/file | OS-variant dependent additions |
Mac OS (HFS+) | / | 255 Unicode chars | /dir/file | dir/file | Mac OS legacy support, BSD extended attributes |
Windows based OS (NTFS) | \\ | 255 Unicode chars | Drive:\\dir\\file | dir\\file | File encryption and compression |
DOS (basic FAT) | \\ | 8.3 | Drive:\\dir\\file | dir\\file | Attributes |
Using Perl to deal with different Filesystems
By now we know all the filesystems differ from each other and to deal with these in Perl we use File::Spec module. This module is used to hide the differences between these filesystems. Let us learn how we use this module. We will use the catfile method to get the path of the file.
Example:
use File::Spec;
my $path= File::Spec->catfile(qw{home user Desktop file.txt});
In this way the scalar variable $path get sets to home\user\desktop\file.txt in a Windows operating system. and in Unix based system it gets set to home/user/Desktop/file.txt. The File::Spec module also contains methods like curdir and updir to get the current directory (.) and up-directory (..).
You may also use the moudle Path::Class which is an another good wrapper. You will have to install it before using.
Below is an example of how it works:
use Path::Class;
my $file = file (qw{home user Desktop file.txt});
my $dir = file (qw{home user Desktop});
The $file and $dir are scalar variable which contains the path to the file.txt file and Desktop directory respectively.
Here’s the path
print $file;
print $dir;
The output will depend on operating system. If it is Unix then it will yield
home/user/desktop/file.txt and home//user//desktop
and in Windows based systems it will give
home\\user\\desktop\\file.txt and home\\user\\desktop
Here $file and $dir are objects which have several methods which can be applied on them for some use. Like absoulte method gives the absolute path and slurp method slurps through the file’s contents.
my $abspath = $file->absolute;
my $content = $file->slurp;
$file->remove(); #delete the file
When you want to write a code for a particular system and you want to make this system understand the path of other operating system then you may use foreign_file() and foreign_dir() methods. These will return the path based the argument which you have to specify explicitly.
use Path::Class qw(foreign_file foreign_dir);
my $foreignfile = foreign_file('Win32', qw{home user Desktop file.txt});
my $foreigndir = foreign_dir('Win32', qw{home user});
Now $foreignfile will contain home\\user\\desktop\\file.txt even if the code is run from a Unix based system. This approach is very handy and useful. In the next article we will continue and expand our discussion.
I just, what?
Windows (2000+) will convert unix style path separators seamlessly, so this module doesn’t appear useful at all. Just use unix style path seperators, always.
Isn’t it better to do it explicitly than depending on the implicit conversion which may do something wrong which you are not aware of? It is not good to rely on the architecture to do the things for you. You should define things explicitly, in that case you can be sure that your code will do the things which you have ordered it to do.