Как найти домашний каталог пользователя в Perl?

46

Мне нужно проверить, существует ли файл в домашнем каталоге пользователя, поэтому используйте проверку файла:

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

Несмотря на то, что в домашнем каталоге пользователя есть файл с именем foo.txt, Perl всегда жалуется, что такого файла или каталога нет. Когда я заменяю "~" на /home/jimmy (скажем, пользователь jimmy), то Perl дает правильный вердикт.

Не могли бы вы объяснить, почему "~" не работает в Perl и рассказывать мне, что такое Perl-способ найти домашний каталог пользователя?

  • 17
    ~ это оболочка Вот почему это не работает в Perl. :)
  • 0
    Вы также можете увидеть это следующим образом : если это должно было работать, то Perl придется заменить тильды в каждой строке вашей домашней директории. Тогда вам всегда придется избегать тильды в каждой строке, которую вы пишете. Также сравните с bash: если вы хотите расширение тильды, тогда ваша строка не должна быть в кавычках, иначе bash не расширит ее. Так что на самом деле вы могли бы сказать, что Perl работает точно так же, как Bash: если тильда заключена в кавычки, она не делает ничего особенного. ;)
Теги:
home-directory
tilde-expansion

5 ответов

64
Лучший ответ

~ является bash -ism, а не a perl -ism, поэтому он не работает. Учитывая, что вы, похоже, используете систему типа UNIX, возможно, самым простым решением является использование переменной среды $HOME, например:

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

И да, я знаю, что пользователь может изменить свою переменную среды $HOME, но тогда я бы предположил, что они знают, что они делают. Если нет, они заслуживают всего, что получают: -)

Если вы хотите сделать это правильно, вы можете посмотреть File:: HomeDir, который намного более ориентирован на платформу. Вы можете увидеть его в действии в следующем script 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";
}

и расшифровка стенограммы:

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

pax$ rm -rf ~/foo.txt ; perl chkfile.pl
No, it doesn't!
  • 10
    В этом есть пара проблем: не во всех сессиях установлен HOME, и не все системы строят свои пути, как unix. File :: HomeDir даст вам правильный ответ.
  • 8
    Никогда не предполагайте, когда вам это не нужно. Полезные программы имеют тенденцию мигрировать. :)
Показать ещё 2 комментария
57

Я не уверен, как все пропустили File::HomeDir. Это одна из тех трудных задач, которые звучат легко, потому что никто не знает обо всех пустых исключениях, о которых вы должны думать. Он не поставляется с Perl, поэтому вам нужно установить его самостоятельно.

Как только вы узнаете домашний каталог, постройте путь, который вам нужен, File::Spec:

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

 print "The path is ", catfile( home(), 'foo.txt' ), "\n";
  • 0
    или используйте с File::chdir (мой любимый модуль CPAN): ... use File::chdir; { local $CWD = home; if (-e $file) { ... } } , не зависит от платформы, блокирует управление локальным рабочим каталогом!
15

Вы можете glob тильда, glob('~/foo.txt') должна работать. Или вы можете использовать модуль File::Save::Home, который также должен заботиться о других системах.

  • 6
    Почему отрицательный голос? Оба подхода работают. Если есть проблема с ними, я хотел бы знать.
  • 0
    Привет, я только начинающий, но если у меня есть домашний каталог .jpg и я запускаю: print glob ('~ / *. Jpg'); это ничего не делает. но если я запускаю: print glob ('Users / Daniel / *. jpg'); он печатает: /Users/Daniel/JanesJinormousJugs.jpg
Показать ещё 1 комментарий
11

Домашний каталог для пользователя хранится в /etc/passwd. Лучший способ получить информацию - getpw* функции:

#!/usr/bin/perl 

use strict;
use warnings;

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

Чтобы решить вашу конкретную проблему, попробуйте этот код:

if ( -e (getpwuid $>)[7] . "/foo.txt" ) {
   print "yes ,it exists!";
}
  • 1
    File :: HomeDir не является основным модулем, поэтому это может быть хорошим вариантом, если вы не хотите добавлять зависимость.
7

Попробуйте File::Path::Expand.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню