2009-09-25 7 views
48

Je dois vérifier si un fichier dans un répertoire personnel de l'utilisateur existe donc utiliser la vérification du fichier:Comment trouver le répertoire personnel d'un utilisateur dans Perl?

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

Même si il y a un fichier appelé foo.txt sous le répertoire de l'utilisateur, Perl toujours se plaint il n'y a pas de fichier ou de répertoire. Quand je remplace "~" par /home/jimmy (disons que l'utilisateur est jimmy) alors Perl donne le bon verdict.

Pourriez-vous expliquer pourquoi "~" ne fonctionne pas en Perl et dites-moi quel est le chemin de Perl à pour trouver le répertoire personnel d'un utilisateur?

+17

~ est une chose shell. C'est pourquoi cela ne fonctionne pas en Perl. :) –

Répondre

63

~ est un bash -ism plutôt qu'un perl -ism, ce qui explique pourquoi cela ne fonctionne pas. Étant donné que vous semblez être sur un système de type UNIX, probablement la solution plus facile est d'utiliser la variable d'environnement $HOME, tels que:

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

Et oui, je sais que l'utilisateur peut changer leur variable d'environnement $HOME mais alors je suppose qu'ils savent ce qu'ils font. Sinon, ils méritent tout ce qu'ils obtiennent :-)

Si vous voulez faire le droit façon, vous pouvez regarder dans File::HomeDir, ce qui est beaucoup plus plate-forme savvy. Vous pouvez le voir en action dans le script suivant chkfile.pl:

use File::HomeDir; 
$fileSpec = File::HomeDir->my_home . "/foo.txt"; 
if (-e $fileSpec) { 
    print "Yes, it exists!\n"; 
} else { 
    print "No, it doesn't!\n"; 
} 

et transcription:

 
pax$ touch ~/foo.txt ; perl chkfile.pl 
Yes, it exists! 

pax$ rm -rf ~/foo.txt ; perl chkfile.pl 
No, it doesn't! 
+10

Il y a quelques problèmes avec ceci: toutes les sessions n'ont PAS de HOME, et tout le système ne construit pas ses chemins comme unix. File :: HomeDir vous donnera la bonne réponse. –

+8

Ne supposez jamais que vous n'en avez pas besoin. Les programmes utiles ont tendance à migrer.:) –

+0

Un _really_ réponse tardive à cela, mais il pourrait être utile pour les lecteurs actuels - une alternative est d'utiliser 'glob ('~/foo.txt')'. Cela a l'avantage de développer correctement des choses comme '~ user123/foo.txt'. Je me suis rendu compte que le PO mentionnait spécifiquement le répertoire personnel, mais je suis tombé sur ce sujet lorsque je cherchais quelque chose de plus générique, et j'ai pensé que j'aiderais les autres à suivre le même chemin. – John

11

Le répertoire d'un utilisateur est stocké dans /etc/passwd. La meilleure façon d'obtenir l'information est le getpw* functions:

#!/usr/bin/perl 

use strict; 
use warnings; 

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

Pour résoudre votre problème, essayez ce code:

if (-e (getpwuid $>)[7] . "/foo.txt") { 
    print "yes ,it exists!"; 
} 
+1

File :: HomeDir n'est pas un module de base, donc cela peut être une bonne option si vous ne voulez pas ajouter une dépendance. – CoverosGene

14

Vous pouvez glob le tilde, glob('~/foo.txt') devrait fonctionner. Ou vous pouvez utiliser le module File::Save::Home qui devrait également prendre en charge d'autres systèmes.

+6

Pourquoi le downvote? Les deux approches fonctionnent. S'il y a un problème avec eux, j'aimerais savoir. – zoul

+0

Salut, je suis juste un débutant, mais si j'ai un .jpg dans mon répertoire personnel Win 7 et que je lance: print glob ('~/*. Jpg'); ça ne fait rien. mais si je cours: print glob ('Users/Daniel/*. jpg'); il imprime: /Users/Daniel/JanesJinormousJugs.jpg – Literat

+0

Solution non-portable très élégante. Si vous avez un script Perl qui est écrit pour fonctionner spécifiquement dans un environnement Linux (par exemple, vous déballez des scripts bash, alors vous ne perdez rien en le faisant de cette façon, comme vous êtes déjà non-portable) –

56

Je ne sais pas comment tout le monde a raté File::HomeDir. C'est une de ces tâches difficiles qui semblent faciles parce que personne ne connaît toutes les exceptions loufoques auxquelles vous devez penser. Il ne vient pas avec Perl, vous devez donc l'installer vous-même.

Une fois que vous connaissez le répertoire, construire le chemin que vous avez besoin avec File::Spec:

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

print "The path is ", catfile(home(), 'foo.txt'), "\n"; 
+0

ou utilisez avec 'File :: chdir' (mon module préféré CPAN):' ... utilise File :: chdir; {local $ CWD = home; if (-e $ file) {...}} ', indépendant de la plate-forme, bloque la gestion du répertoire de travail local! –

Questions connexes