Я хотел бы выполнить ls
в программе Perl как часть сценария CGI. Для этого я использовал exec(ls)
, но это не возвращается из вызова exec
.
Есть ли лучший способ получить список каталогов в Perl?
Я хотел бы выполнить ls
в программе Perl как часть сценария CGI. Для этого я использовал exec(ls)
, но это не возвращается из вызова exec
.
Есть ли лучший способ получить список каталогов в Perl?
Exec вообще не возвращается. Если вы этого хотите, используйте system.
Если вы просто хотите прочитать каталог, open/read/close-dir может быть более подходящим.
opendir my($dh), $dirname or die "Couldn't open dir '$dirname': $!";
my @files = readdir $dh;
closedir $dh;
#print files...
.
и ..
(для текущего и родительского каталога), то вам нужно: my @files = grep { !/^\.\.?$/ } readdir $dh;
.
- person Platinum Azure; 11.08.2010
Все остальные, кажется, застряли на исполнительной части вопроса.
Если вам нужен список каталогов, используйте встроенные в Perl glob
или opendir
. Вам не нужен отдельный процесс.
exec не возвращает управление программе perl. system будет, но не возвращает результаты ls, а возвращает код состояния. отметки `` дадут вам вывод нашей команды, но некоторые считают это небезопасным.
Используйте встроенные функции dir. opendir, readdir и так далее.
http://perldoc.perl.org/functions/opendir.html
http://perldoc.perl.org/functions/readdir.html
Чтобы получить вывод системной команды, вам нужно использовать обратные кавычки.
$listing = `ls`;
Однако Perl хорошо справляется с каталогами. Я бы рекомендовал использовать File::Find::Rule.
Используйте Perl Globbing:
my $dir = </dir/path/*>
Еще один пример:
chdir $dir or die "Cannot chroot to $dir: $!\n";
my @files = glob("*.txt");
РЕДАКТИРОВАТЬ: Упс! Я думал, вам просто нужен список каталогов... удалите вызов "каталог", чтобы этот скрипт делал то, что вы хотите...
На мой взгляд, играть с файловыми дескрипторами - неправильный путь. Ниже приведен пример использования File::Find::Rule для поиска всех каталогов в указанном каталоге. Это может показаться чрезмерным убийством за то, что вы делаете, но позже это может стоить того.
Во-первых, мое однострочное решение:
File::Find::Rule->maxdepth(1)->directory->in($base_dir);
Теперь более растянутая версия с комментариями. Если у вас установлен File::Find::Rule, вы сможете запустить его без проблем. Не бойтесь CPAN.
#!/usr/bin/perl
use strict;
use warnings;
# See http://search.cpan.org/~rclamp/File-Find-Rule-0.32/README
use File::Find::Rule;
# If a base directory was not past to the script, assume current working director
my $base_dir = shift // '.';
my $find_rule = File::Find::Rule->new;
# Do not descend past the first level
$find_rule->maxdepth(1);
# Only return directories
$find_rule->directory;
# Apply the rule and retrieve the subdirectories
my @sub_dirs = $find_rule->in($base_dir);
# Print out the name of each directory on its own line
print join("\n", @sub_dirs);
Я бы порекомендовал вам взглянуть на IPC::Open3. Это позволяет гораздо больше контролировать порожденный процесс, чем система или обратные кавычки.
В Linux я предпочитаю найти:
my @files = map { chomp; $_ } `find`;
find $theDir -maxdepth 1 -type f -mtime -2
;
- person Michael Rush; 09.03.2012