Leo Charre

NAME

File::PathInfo - oo access to path variables stat data about a file on disk

SYNOPSIS

        use File::PathInfo;
        
        my $f = new File::PathInfo;
   
        $f->set('/home/myself/public_html/folder/stew.txt) or die('file does not exist');
        
        $f->is_text; # returns 1
   
        $f->ext; # returns 'txt'
   
        $f->abs_loc; # returns '/home/myself/public_html/folder'

DESCRIPTION

This provides an object oriented interface to things you want to know about a file, such as extension, absolute path, relative path, size, filename (without extension), etc. It is a sort of swissarmy knife of file info.

A lot of times you need to know a file's absolute path, it's absolute location, maybe it's relative location to something else (like DOCUMENT ROOT), then you need to maybe know the relative path and relative location for a file. You need to know if a file is a directory, what it's extension is. You can commonly use regexes to do this.

This module provides commonly needed variables.

Works with relative paths like in a website too:

        use File::PathInfo;
        
        my $f = new File::PathInfo;
   
        $f->set('folder/stew.txt) or die('file does not exist');
   
        $f->abs_path; # returns '/home/myself/public_html/folder/stew.txt'
   
        $f->rel_path; # returns 'folder/stew.txt'
        
        $f->rel_loc; # returns 'folder'
   
        $f->is_in_DOCUMENT_ROOT; # returns 1

Also safeguards from cgi accessing files outside of document root

        use File::PathInfo;
        
        my $f = new File::PathInfo;
   
        $f->set('/home/myself/stew.txt) or die('file does not exist');
   
        $f->rel_path; # throws exception and complains that it is not in document root

You can define also, that document root is something else. To assure the files you are dealing with remain in a certain part of the filesystem tree. Also lets you set a different document root, if you want an application to serve files in some other place, but you still want to restrict what the script can access to within that slice of the filesystem:

        use File::PathInfo;
        
        my $f = new File::PathInfo({ DOCUMENT_ROOT => '/home/myself/sharethese' });
   
        $f->set('/home/myself/sharethese/stew.txt) or die('file does not exist');
   
        $f->rel_path; # returns 'stew.txt'

Realize that for the rest of your cgi, ENV DOCUMENT ROOT is still your webshare, public html, etc. It's just that you can override for the object instance, what the DOCUMENT ROOT is.

By default if you want to get path info on a file that is not on disk, an exception is thrown. If you want to disable that:

        use File::PathInfo({ check_exist => 0 });
        
        my $f = new File::PathInfo;
   
        $f->set('/home/myself/html/sty54wyw5/4y54yy4ew.txt') ;
   
        $f->rel_path; # returns 'sty54wyw5/4y54yy4ew.txt'

Maybe this could be useful if you wanted to work with a path string that *was* present or *will be*.

Absolute path methods are accessible always. The relative path methods are accessible *if* you have DOCUMENT ROOT environment variable set or if you pass the argument DOCUMENT_ROOT to object constructor.

If you are using cgi, ENV DOCUMENT_ROOT is set when you call the program via http (the browser). But when you call the program via the cli (command line) it will likely not be set! This causes some programs to crash when you run then on the command line, and you scratch your head and ask 'how come?'. The same goes for the environment variable 'HOME', which is not set when you call your cgi script via http (browser) but is set if you call it via cli (the command line, shell access, etc.).

METHODS

new()

Argument is either a hash ref or an absolute or relative path to a file.

        my $fi = new File::PathInfo;
        $fi->set('/home/myself/html/file.txt');
   
        # or
   
        my $fi = new File::PathInfo('/home/myself/html/file.txt');

Optional parameters to constructor:

        my $fi = new File::PathInfo({ 
                DOCUMENT_ROOT => '/home/myself/html',
                check_exist => 0,
                time_format => 'yyyy/mm/dd hh::mm',
        });
'check_exist'

Defaults to true. If a file does not exist, methods return undef.

'DOCUMENT_ROOT'

Set a different document root variable from the one currently on server. This variable must be set either in the server or via this argument if you will use the relative file path methods.

set()

Unless you provide an argument to the constructor, set() must be called. You can use set() to iterate through a list of paths. Argument is a relative or absolute file path.

        $f->set('/tmp/trashdir'); # absolute path
   
        $f->set('gfx/logo.gif'); # relative to DOCUMENT ROOT
   
        $f->set('./thisfile.png'); # relative to current working directory

Method set() returns abs path. If the file cannot be resolved to disk then it warns and returns undef. If you then call any methods, exceptions are thrown with Carp::croak.

You can do this too:

        $f->set('/home/myself/html/documents/manual.pdf') or die( $File::PathInfo::errstr );
        
        $f->set('documents/manual.pdf') or print "Location: 404.html\n\n" and exit; 

Returns abs path resolved to item in question.

get_datahash()

Takes no argument. Returns all elements, in a hash.

Try it out:

        #!/usr/bin/perl -w
        use File::PathInfo;
        use Smart::Comments '###';
        my $f = new File::PathInfo;     
        $f->set '/home/bubba'
        my $hash = $f->get_datahash;
        ### $hash

Prints out:

        ### $hash: {
        ###          abs_loc => '/home',
        ###          abs_path => '/home/bubba',
        ###          atime => 1173859680,
        ###          atime_pretty => '2007/03/14 04:08',
        ###          blksize => 4096,
        ###          blocks => 8,
        ###          ctime => 1173216034,
        ###          ctime_pretty => '2007/03/06 16:20',
        ###          dev => 2049,
        ###          filename => 'bubba',
        ###          filename_only => 'bubba',
        ###          filesize => '4096',
        ###          filesize_pretty => '4k',
        ###          gid => 0,
        ###          ino => 3626597,
        ###          is_binary => 1,
        ###          is_dir => 1,
        ###          is_file => 0,
        ###          is_text => 0,
        ###          is_topmost => 0,
        ###          mode => 16877,
        ###          mtime => 1173216034,
        ###          mtime_pretty => '2007/03/06 16:20',
        ###          nlink => 3,
        ###          rdev => 0,
        ###          size => '4096',
        ###          uid => 0
        ###        }

errstr()

Returns errot string or undef if no errors are present.

To check for errors you can query the error string.

        $f->set('/home/myself/this') or die($f->errstr);        
        

ABSOLUTE METHODS

The absolute path methods.

abs_loc()

Returns absolute location on disk. Everything but the filename, no trailing file delimiter (slash).

abs_path()

Returns absolute path on disk. Notice that all symlinks are resolved with Cwd::abs_path, so any /../ etc are gone.

filename()

Returns filename, no leading directories, no leading file delimiter (slash).

filename_only()

Returns filename without extension. '/home/myself/this.txt' would return 'this' Does not return undef.

ext()

Returns filename ext, if none found, returns undef.

RELATIVE METHODS

These methods are only available if a DOCUMENT ROOT is defined.

rel_path()

relative to DOCUMENT_ROOT

rel_loc()

location relative to DOCUMENT_ROOT

is_DOCUMENT_ROOT()

if this *is* the document root returns undef if DOCUMENT ROOT is not set.

is_topmost()

if the parent directory is document root. boolean. returns undef if DOCUMENT ROOT is not set.

is_in_DOCUMENT_ROOT()

does this file reside in the DOCUMENT_ROOT tree ? note that DOCUMENT_ROOT itself *is* the document root, does is not considered to be *in* the document root. this is partly for security reasons.

DOCUMENT_ROOT()

Returns doc root, returns undef if not set, or if it cant resolve to abs path on disk. You can override the DOCUMENT root like this:

        my $fi = new File::PathInfo('./path/to/file.tmp',{ DOCUMENT_ROOT => '/home/myself' });

Doc root is also resolved for symlinks and . and .. etc.

Using a custom DOCUMENT_ROOT variable for the object instance does not alter the variable for other cgi programs, etc. Just for the object you created. It is only used internally, If this class is inherited, $ENV{DOCUMENT_ROOT} is whatever it is set at on the server. If you provide a different DOCUMENT_ROOT as an argument, $ENV{DOCUMENT_ROOT} still returns the server set variable. It is method DOCUMENT_ROOT() that returns the internally used value.

You do not have to provide a DOCUMENT_ROOT value to the constructor, the variable is not needed unless you use the relative path methods

Again, the order of priority to define what the DOCUMENT ROOT is for an instance of File::PathInfo is:

First, in argument to contructor

Second, if your environment variable DOCUMENT_ROOT is set.

You can also call DOCUMENT_ROOT_set()

DOCUMENT_ROOT_set()

argumnent is abs path to document root will warn if not a dir on disk

STAT METHODS

These methods ask useful things like, is the file a directory, is it binary, is it text, what is the mtime, etc. These methods load data on call, they can be expensive if you are looping through thousands of files. So don't worry because if you don't need them, they are not called. Using one or more of these methods makes one stat call only.

is_binary()

returns boolean true or false.

is_text()

returns boolean true or false.

is_dir()

returns boolean true or false.

is_file()

returns boolean true or false.

ctime()

atime()

mtime()

uid()

ino()

blksize()

blocks()

dev()

gid()

mode()

rdev()

size()

filesize_pretty()

Returns filesize in k, with the letter k in the end returns 0k if filesize is 0 .

ctime_pretty()

atime_pretty()

mtime_pretty()

Returns these timestamps formatted to 'yyyy/mm/dd hh:mm' by default. To change the format, pass it as argument to object constructor as such:

        my $r = new File::PathInfo({ time_format => 'yyyy_mm_dd' });
        
        $r->set('/home/myself/archive1.zip');
        
        $r->ctime_pretty; # now holds 1999_11_13
   

filesize()

Returns filesize in bites.

PROCEDURAL SUBROUTINES

None of these functions are exported by default. These subs are used by the oo methods internally, and you can use them in your code also by the normal import ways:

        use File::PathInfo ':all';
   
        use File::PathInfo qw(abs_path_n);

abs_path_n()

just like Cwd::abs_path() but, does not resolve symlinks. Just cleans up the path. argument is an absolute path.

PACKAGE SETTINGS

Resolve symlinks? Default is 1 ( Not Yet Implemented )

        File::PathInfo::RESOLVE_SYMLINKS = 0;   

Debug

        File::PathInfo::DEBUG = 1;      
        

CAVEATS

This is currently for unix filesystems. File::PathInfo will NOT work on non POSIX operating systems. Trying to set an abs path like C:/something will throw an exception.

The module gets very angry when you set() seomthing like '/etc', anything that sits close to the root of the filesystem. This is on purpose.

TODO

Let people specify a file delimiter for mac and windoze.

Maybe Time::Format is not appropriate here.

BUGS

Please report any bugs to AUTHOR. You can also fill a bug report with http:://rt.cpan.org

PREREQUISITES

Cwd, Carp, Time::Format and possibly Smart::Comments for testing.

SEE ALSO

File::PathInfo::Ext Cwd File::Basename

AUTHOR

Leo Charre leocharre at cpan dot org

COPYRIGHT

Copyright (c) 2009 Leo Charre. All rights reserved.

LICENSE

This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e., under the terms of the "Artistic License" or the "GNU General Public License".

DISCLAIMER

This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the "GNU General Public License" for more details.




Hosting generously
sponsored by Bytemark