2

I am doing a Perl script to attach another variable to the end of the current working directory, but I am having problems with using the module.

  1. If I run getcwd from D:\, the value returned is

    D:/ (with forward slash)  
    

    If I run getcwd from D:\Temp\, the value returned is

    D:/temp (without forward slash)
    

    This makes the situation quite tricky because if I simply do:

    use Cwd;
    $ProjectName = "Project"; # This is a variable supplied by the user
    $directory = getcwd().$ProjectName."\/";
    print $directory."\n";
    

    I will end up with either

    D:/Project (correct)  
    

    or

    D:/TempProject (instead of D:/Temp/Project)
    

    Is this a feature in Cwd? It does not seem to be in the documentation.

  2. I have thought up the following code to solve this issue. It takes 3 lines to do it. Can any of you see a more concise way?

    use Cwd;
    $ProjectName = "Project"; # This is a variable supplied by the user
    
    $directory = getcwd();
    $directory =~ s/(.+?)([^\\\/])$/$1$2\//g;  # Append "/" if not terminating with forward/back slash
    $directory .= $ProjectName."\/";
    
    print $directory."\n";
    
Kevin Panko
  • 8,356
  • 19
  • 50
  • 61
Andy
  • 2,770
  • 9
  • 35
  • 42

2 Answers2

9

Use File::Spec instead of making your own path manipulation routines.

use Cwd;
use File::Spec;

$ProjectName = "Project";

$cwd = getcwd();
$directory = File::Spec->catdir($cwd, $ProjectName);

print "$directory\n";
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • Thank you for making we aware of File::Spec. I have to change my entire script to use catdir and catfile. I am sure that it is better in the long term. – Andy May 29 '09 at 15:36
4

The first case is including the trailing slash because "D:" is a volume specifier. It isn't a valid directory name. "D:/" is analogous to the root directory in Unix/Linux.

Quick and dirty solution:

$directory .= '/' unless $directory =~ m|/$|;

For a robust and portable solution, use File::Spec or File::Spec::Functions if you prefer a non-object-oriented interface:

use Cwd;
use File::Spec::Functions qw(catdir);

my $directory = catdir(getcwd(), $ProjectName);

Note that catdir does not include the trailing slash, and that File::Spec builds paths using the directory separator for the host operating system. (e.g. backslashes on Windows).

Michael Carman
  • 30,628
  • 10
  • 74
  • 122