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

I have a perl script that runs on both UNIX and PCs (Windows). I am given a list of filenames from the user. If the user is on UNIX and specifies the file path with a "~", I need to convert the name to the full path name.

Example: change ~user1/file.a to /home/u1/user1/file.a

I've been using $FullFileName = glob ($FileName);

This works most of the time, but sometimes it returns a null string.

Is there another way of doing this?
Is there a length limitation on glob (I've only seen the null string returned on a very long pathname)?

Replies are listed 'Best First'.
Re: How to convert unix ~path (tilde) to full path
by jwest (Friar) on Apr 05, 2002 at 17:01 UTC
    The 'HOME' environment variable is set to the home directory of the user, so:
    use File::Spec; my $FileName; my $homedir = $ENV{HOME}; if ($FileName =~ /^~/) { $FileName =~ s/^~//; $FileName = File::Spec->catfile($homedir, $FileName); }
    would probably do the trick.
    --jwest


    -><- -><- -><- -><- -><-
    All things are Perfect
        To every last Flaw
        And bound in accord
             With Eris's Law
     - HBT; The Book of Advice, 1:7
    

      It's a little redundant to see if the string begins with a ~ and then remove it, when s/^~// will only return true if it replaced anything.

      Also, it might be nice to fallback to the home directory returned by getpwuid just in case $ENV{'HOME'} isn't set ...

      use File::Spec; my $filename = '~/public_html/'; if ( $filename =~ s<^~([^/]*)/></> ) { my $homedir = $1 ? (getpwnam($1))[7] # specified user : $ENV{'HOME'} || (getpwuid($<))[7] # ourselves or die "Where's your home?\n"; $filename = File::Spec->catfile($homedir, $filename); }

      Update: Fixed to account for jeffenstein's observation.

          --k.


      :

      Unfortunately, that only works for ~/path. The ~ form also works as ~user2, meaning the home directory of user2, not the current user's home directory.

      Something more complete might look like this: Warning: untested code

      my $filename = "~user2/tmp"; if( $filename =~ m@^\~([^/])+@){ my $home = (getpwnam($1))[7]; if( $home){ $filename =~ s@^\~[^/]+@$home@; } }else{ $filename =~ s@^\~@$ENV{'HOME'}@; }

      This should handle both cases.

Re: How to convert unix ~path (tilde) to full path
by Zaxo (Archbishop) on Apr 05, 2002 at 17:18 UTC

    If the program is not running as the user, $ENV{HOME} won't work. getpwnam returns a list with home directory at index seven.

    After Compline,
    Zaxo

      Zaxo speaks the truth... Adapted from The Perl Cookbook (pg.231)...

      my $file = '~rich36/perl/makeperl'; $file =~ s{ ^ ~ ( [^/]* ) } { $1 ? (getpwnam($1))[7] : ( $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($>))[7] ) }ex; print "$file"; __DATA__ /home/users/rich36/perl/makeperl

      Rich36
      There's more than one way to screw it up...

Re: How to convert unix ~path (tilde) to full path
by mtr4cv (Novice) on Apr 08, 2002 at 13:38 UTC
    Thank you for all the useful information. Can't use $ENV{HOME} since the path may not be the user's path.

    I'll look into getpwman.

    I did find another solution at File::Glob that does work:

    use File::Glob ':glob'; $FullFileName = bsd_glob($FileName, GLOB_TILDE);