2013-08-08 2 views
1

Я обнаружил небольшое неправильное поведение в моем скрипте Perl, когда создаю и проверяю наличие каталогов с тильде, что не происходит, если я использую полный путь /home/user. Когда я запускаю этот скрипт в первый раз, он создает новый каталог. Когда я запускаю его во второй раз, он не признает существование каталога, и пытается создать его во второй раз:каталоги тильды (~) в Perl

#!/usr/bin/perl 
use strict; 

my $outdir = '~/test'; 
my $cmd = "mkdir $outdir"; 
unless (-d $outdir) { 
    0 == system($cmd) or die "Error creating outdir $outdir\n $?"; 
} 

1; 


[~] $ rm test/ -rf 
[~] $ perl dir.pl 
[~] $ perl dir.pl 
mkdir: cannot create directory `/home/avilella/test': File exists 
Error creating outdir ~/test 
256 at dir.pl line 7. 

Как я могу надежно иметь дело с каталогами, которые используют знак тильды ~ в Perl ?

+0

У меня нет решения, но проблема заключается в следующем: С «MKDIR ~/тест», символ тильды расширяется оболочкой, используемой вызовом 'system'. С '(-d $ outdir)', оболочка не задействована, а символ тильды не разворачивается, поэтому «~/test» рассматривается как литеральное относительное имя каталога. – Deestan

+2

Ваш rmdir не удался. его не 'rm test/-rf', его' rm -rf test/' –

+0

@Paulchenkiller. Вероятно, это должен быть ответ. – TLP

ответ

11

Тильда интерпретируется оболочкой, что означает ваш домашний каталог.

Поэтому -d оператор Perl видит что-то другое (файл/каталог с именем ~) для вашего вызова оболочки 'mkdir ~/whatever' (который расширяет ~ означает /home/user).

Я бы попытался использовать исключительно функции Perl для выполнения ваших операций. Вы избежите появления новых процессов, и ваш доступ к файлам будет выполняться согласованным образом.

примечание Perl's mkdir встроенная функция. Отметим также File::Glob модуль, который делает выполнить расширение ~ символа (возможно, полезно, если у вас есть пользователи, входящие имена каталогов вручную)

5

Вы можете использовать %ENV домашний каталог, который значения, импортируемые из оболочки:

my $home = $ENV{HOME}; 

Вы также должны знать, что mkdir является Perl встроенные функции:

mkdir "$home/test" or die "Cannot create test: $!"; 
+0

's/^ ~/$ ENV {HOME}/e' будет интересно :) – gaussblurinc

+0

Зачем вам использовать eval? – TLP

+0

Не знаю, привычка, я думаю – gaussblurinc

4

~ является интерпретируется оболочкой, которая вызывается функцией system. Это оболочка, которая заменяет ~ домашним каталогом пользователя. Что касается Perl или ядра, то ~ означает файл или каталог с односимвольным именем, как и любой другой символ. Таким образом, тест, выполненный -d, терпит неудачу, потому что нет каталога с именем ~.

Если вы использовали функцию встроенного в Perl mkdir, а не вызывали внешнюю команду с помощью сценария оболочки, у вас была бы ошибка в этой точке, потому что каталог ~ не существует.

Домашний каталог пользователя почти всегда доступен в переменной окружения HOME. Если вам нравится, вы можете вернуться к опросу базы данных пользователей, если HOME нет, но это ненормальная ситуация. Используйте переменную окружения HOME, если она присутствует, потому что иногда полезно изменить ее для запуска программы с различными конфигурационными файлами, а переменная среды всегда доступна на практике, тогда как пользовательская база данных может быть недоступна из-за проблем с сетью в некоторых конфигурации (например, NIS или LDAP).

my $home_directory = $ENV{HOME}; 
if (!defined $home_directory) {$home_directory = getpwuid($<);} 
my $outdir = "$home_directory/test"; 
unless (-d $outdir) { 
    mkdir $outdir or die "Error creating $outdir: $!\n" 
} 
2

Ваш скрипт не может создавать существующие каталоги.Это ошибка, которую вы представили нам:

[~] $ rm test/ -rf 
[~] $ perl dir.pl 
[~] $ perl dir.pl 
mkdir: cannot create directory `/home/avilella/test': File exists 
Error creating outdir ~/test 
256 at dir.pl line 7. 

Проблема заключается в строке вашего удаления:

[~] $ rm test/ -rf 

неправильно. Как и большинство команд, правильный синтаксис будет:

[~] $ <command> <options> <parameters> 

так было бы:

[~] $ rm -rf test/ 
+0

Я часто делаю что-то вроде 'rm test/-rf' в bash, и это работает. В чем тут разница? – EverythingRightPlace

Смежные вопросы