aca has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I am trying to cut the directory path in the Perl. Here is my code
my $filespec = "/usr/share/directory/piano_book.mp4";
How can i cut the first two directories i.e. /usr/share/ and i want only /directory/piano_book.mp4? Any help will be appreciated. Thanks in advance.

Replies are listed 'Best First'.
Re: How to cut the directory path?
by kevbot (Vicar) on Feb 10, 2016 at 07:17 UTC
    There are quite a few different ways that you could perform this task. Whenever, I'm dealing with file paths I like to use Path::Tiny. For example,
    #!/usr/bin/env perl use strict; use warnings; use Path::Tiny; my $filespec = "/usr/share/directory/piano_book.mp4"; my $path = path($filespec); my $rel = $path->relative("/usr/share"); print $rel, "\n"; exit;
    This article is a good intro to Path::Tiny.
      How it can be done using regular expression?
        If you really want to use regex, you could do this:
        my $filespec = "/usr/share/directory/piano_book.mp4"; my $relative = "." . $1 if $filespec =~ m{/usr/share(.*)};
        Or you could use split and then paste together the pieces you need.

        But you'd most probably be better off with a specialized module such as Path::Tiny mentioned above or some other.

        How it can be done using regular expression?

        You let Path::Tiny use File::Spec which uses regular expressions for you.

        I would also advise using established modules for this, but here's another regex-only way to remove the first n directories from an absolute path. It looks like you're using a *nix path, and I haven't made the effort to define a proper directory pattern in  $dir (I don't think that any character other than a  / is allowed), so you will have to fix up the  [^/] character class accordingly.

        c:\@Work\Perl\monks>perl -wMstrict -le "my $filespec = '/usr/share/directory/piano_book.mp4'; print qq{absolute: '$filespec'}; ;; my $dir = qr{ / [^/]+ }xms; # fix [^/] ;; my $n = 2; die qq{'$filespec' could not be made relative} unless $filespec =~ s{ \A (?: $dir){$n} }{.}xms; print qq{relative: '$filespec'}; " absolute: '/usr/share/directory/piano_book.mp4' relative: './directory/piano_book.mp4'
        Please see perlre, perlretut, and perlrequick.

        Update: Added error check to substitution in example code.


        Give a man a fish:  <%-{-{-{-<

Re: How to cut the directory path?
by Discipulus (Canon) on Feb 10, 2016 at 08:52 UTC
    You can use File::Spec directly if you want

    use strict; use warnings; use File::Spec; my(undef,$dir,$file)=File::Spec->splitpath( 'c:\Perl\bin\perl.exe' ); my @dirs = File::Spec->splitdir($dir); # splitdir returns some '' empty dirs # docs tell: # Unlike just splitting the directories on the separator, empty direct +ory names ('' ) can be returned, # because these are significant on some OSes. # # infact adding # use Data::Dump; dd @dirs; # returns # ("", "Perl", "bin", "") # because of this i use the last one among those who contain something # or (grep {/./} @dirs)[-1] print File::Spec->catfile('',(grep {/./} @dirs)[-1],$file); # the first empty '' passed to catfile is needed if you want the leadi +ng separator

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: How to cut the directory path?
by GotToBTru (Prior) on Feb 10, 2016 at 17:29 UTC

    If what is wanted is really the lowest level directory plus file name, try this:

    my $filespec = '/usr/share/directory/piano_book.mp4'; my @parts = split /\//, $filespec; my $relative = './' . join '/', splice @parts,-2,2;
    But God demonstrates His own love toward us, in that while we were yet sinners, Christ died for us. Romans 5:8 (NASB)