views:

1261

answers:

6

I need to check whether a file in a user's home directory exists so use file check:

if ( -e "~/foo.txt" ) {
   print "yes, it exists!" ;
}

Even though there is a file called foo.txt under the user's home directory, Perl always complains that there is no such file or directory. When I replace "~" with /home/jimmy (let's say the user is jimmy) then Perl give the right verdict.

Could you explain why "~" dosen't work in Perl and tell me what is Perl's way to find a user's home directory?

+2  A: 

Try File::Path::Expand.

phoebus
+15  A: 

I think ~ is a bash-ism rather than a perl-ism. I would just use the $HOME environment variable, such as:

if ( -e $ENV{"HOME"} . "/foo.txt" ) {
    print "yes ,it exists!" ;
}

And yes, I know the user can change their $HOME environment variable but then I would assume they know what they're doing. If not, they deserve everything they get :-)

paxdiablo
There are a couple of problems with this: not all sessions have HOME set, and not everything system constructs their paths like unix. File::HomeDir will give you the right answer.
brian d foy
I assumed they were working in a UNIX-like environment since that was the form their home directory took in the question.
paxdiablo
Never assume when you don't need to. Useful programs tend to migrate. :)
brian d foy
A: 

There's a recipe for tilde expansion in The Perl Cookbook.

bstpierre
That is almost certainly a pirated copy of the book, please don't post author's work without their permission.
Chas. Owens
He didn't post the authors work - he linked to a site on the net. If the author wants to go after the guy that *infringed*, they should. I love the misspelling of orelly in the URL :-)
paxdiablo
He posted a link to it, which is morally (if not legally) the same to me.
Chas. Owens
S'ok. To each their own. @bstpierre, I would just link to an Amazon copy of the book for sale then paste in the relevant code to your answer. I tend to prefer answers that aren't just links anyway (what happens if that site goes away?).
paxdiablo
Doh! Sorry for the bogus link, not quite sure what I was thinking when I posted it... thanks for the edits.
bstpierre
Uh, what? O'Reilly specifically authorized Google Books to host their technical books. This is not a pirated copy.
jrockway
The link was updated a couple of times, so you're seeing the final link, not the eastern europe pirate site with the HTML version.
brian d foy
A: 

The home directory for a user is stored in /etc/passwd. The best way to get at the information is the getpw* functions:

#!/usr/bin/perl 

use strict;
use warnings;

print "uid:", (getpwuid 501)[7], "\n",
    "name:", (getpwnam "cowens")[7], "\n";

To address your specific problem, try this code:

if ( -e (getpwuid $>)[7] . "/foo.txt" ) {
   print "yes ,it exists!";
}
Chas. Owens
File::HomeDir is not a core module, so this might be a good option if you don't want to add a dependency.
CoverosGene
+3  A: 

You can glob the tilde, glob('~/foo.txt') should work. Or you can use the File::Save::Home module that should also take care of other systems.

zoul
Why the downvote? Both of the approaches work. If there’s an issue with them, I’d like to know.
zoul
+34  A: 

I'm not sure how everyone missed File::HomeDir. It's one of those hard tasks that sound easy because no one knows about all of the goofy exceptions you have to think about. It doesn't come with Perl, so you need to install it yourself.

Once you know the home directory, construct the path that you need with File::Spec:

 use File::HomeDir qw(home);
 use File::Spec::Functions qw(catfile);

 print "The path is ", catfile( home(), 'foo.txt' ), "\n";
brian d foy