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

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

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

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

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

6 ответов

Решение

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

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

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

Если вы хотите сделать это правильно, вы можете взглянуть на File:: HomeDir, который гораздо лучше ориентирован на платформу. Вы можете увидеть это в действии в следующем скрипте 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
Да, это существует!

pax$ rm -rf ~/foo.txt; perl chkfile.pl
Нет!

Я не уверен, как все пропустили 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";

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

Домашний каталог для пользователя хранится в /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!";
}

Пытаться File::Path::Expand,

Перенесемся в 2020 год, и теперь в perl, начиная с версии 5.31.10, в его основе есть модуль File :: Glob, который разрешает тильду, например:

      perl -MFile::Glob=":bsd_glob" -lE 'say File::Glob::bsd_glob( "~john" )'

произведет: /home/john

или же

      perl -MFile::Glob=":bsd_glob" -lE 'say File::Glob::bsd_glob( "~/some/folder" )'

произведет: /home/jack/some/folder

Модуль File :: Glob существует с perl v5.6, но только с glob подпрограмма, которая устарела.

Другие вопросы по тегам