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

Hi everyone,

I'm just learning how to work with modules and am stuck at the very beginning. File::Basename seems simple enough but ... anyway, here's the sample code:
use File::Basename; my $name = "C:\karate\kid\sucks"; my $basename = basename($name); print "$basename\n";
I've also tried just about every variation of this. With and without the "C:", lower case "c", "basename($name)" with brackets, without, ... you get the idea. In any scenario, it either crashes or returns back the original $name with some random characters missing.

Although I'm using Windows, I decided to try the Unix code "/karate/kid/sucks" and it works. What the hell? Isn't this module supposed to detect the shell I'm using? What am I doing wrong?

Thanks.

Replies are listed 'Best First'.
Re: Simple modules
by BrowserUk (Patriarch) on Jan 31, 2009 at 13:12 UTC

    Either use forward slashes in your pathname literals (even on windows; perl'll sort it out for you), or double your backslashes to avoid them being treated as escapes:

    my $name = "C:/karate/kid/sucks"; # or my $name = "C:\\karate\\kid\\sucks";

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Simple modules
by CountZero (Bishop) on Jan 31, 2009 at 16:24 UTC
    Adding "use warnings;" at the top of your code would have told you:
    Unrecognized escape \k passed through at C:\Data\Perl\Script\Perl-1.pl + line 6. Unrecognized escape \k passed through at C:\Data\Perl\Script\Perl-1.pl + line 6. Unrecognized escape \s passed through at C:\Data\Perl\Script\Perl-1.pl + line 6.
    immediately hinting to you that the \k, \k and \s are being interpolated.

    To avoid this, use single quotes:

    my $name = 'C:\karate\kid\sucks';
    Of course the answer still 'sucks' ;-)

    This behaviour has nothing to do with the module not "understanding" what shell or OS you are using, the interpolation already happens when you assign "C:\karate\kid\sucks" to the variable. There is no way Perl can know at that moment that this string is a filepath and that it should not use \ as an escape sequence. After all by double-quoting the string you specifically indicated that you want this to be interpolated!

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Simple modules
by locked_user sundialsvc4 (Abbot) on Jan 31, 2009 at 17:22 UTC

    Two things:

    (1) Perl is specifically designed so that a program “just works, even on Windows.” Take that program to a Linux box and ... without source-code changes ... it still works. Therefore, a consistent nomenclature is used, regardless of the peculiarities of the host system:

    • Forward slashes are used in file paths (and module paths).
    • Backward slashes are used to indicate character escapes.
    • There is a rich set of File:: modules (and the like) ... standard, and in CPAN ... which are designed to “insulate” your program from environment-specific concerns. If you want a file-path that “just works,” even if you move your app from Linux to Windows ... you got it.

      (2) When you use a module, the various subs in it are not automatically “exported” from it. (The module author can of course specify that it should be so, and you can specify exactly what you do want to export... that's why you sometimes see a list of names on a use statement.)

      In your specific case, the documentation in perldoc File::Basename clearly shows (in its SYNOPSIS) that by default the symbol basename will be exported. You seem to be using the exported routine correctly. But as you move forward with your learning of modules, you'll need to be familiar with (and to understand the reasoning for), idioms like these:

      • use File::Basename qw/basename/;
      • $foo = File::Basename::basename($bar);

Re: Simple modules
by Anonymous Monk on Jan 31, 2009 at 14:22 UTC
    Now would be a good time to skim the docs related to interpolation.
Re: Simple modules
by neutron (Sexton) on Jan 31, 2009 at 14:03 UTC
    Hmm ... makes complete sense. ty.