Как мне получить список каталогов в Perl?

Я хотел бы выполнить ls в программе Perl как часть сценария CGI. Для этого я использовал exec(ls), но это не возвращается из вызова exec.

Есть ли лучший способ получить список каталогов в Perl?


person user28280    schedule 15.10.2008    source источник
comment
система(ы); сделал бы именно это.   -  person access_granted    schedule 12.02.2020


Ответы (9)


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...
person Leon Timmermans    schedule 15.10.2008
comment
Проверьте возвращаемое значение системных команд: opendir... or die... $! Или используйте автоумирание; сделать их фатальными по умолчанию. Я знаю, что это просто придирка, но когда вы даете советы новичкам, это важный урок для них. - person tsee; 15.10.2008
comment
В случае, если кто-то задается вопросом, почему readdir и Closedir не проверяются: у обоих есть только одна возможная ошибка, «недопустимый дескриптор каталога». Поскольку я сам открывал и проверял, могу с уверенностью предположить, что он действителен. Кроме того, в контексте списка readddir все равно не может быть проверен. - person Leon Timmermans; 15.10.2008
comment
Если вам НЕ нужны точечные файлы, вы можете сделать: my @files = grep { !/^\./ } readdir $dh; - person Ranguard; 17.10.2008
comment
Если вам нужны файлы, начинающиеся с точки, но не с . и .. (для текущего и родительского каталога), то вам нужно: my @files = grep { !/^\.\.?$/ } readdir $dh;. - person Platinum Azure; 11.08.2010

Все остальные, кажется, застряли на исполнительной части вопроса.

Если вам нужен список каталогов, используйте встроенные в Perl glob или opendir. Вам не нужен отдельный процесс.

person brian d foy    schedule 15.10.2008
comment
В частности, glob делает именно то, что вам нужно: возвращает массив имен файлов в папке. - person Robert P; 17.10.2008

exec не возвращает управление программе perl. system будет, но не возвращает результаты ls, а возвращает код состояния. отметки `` дадут вам вывод нашей команды, но некоторые считают это небезопасным.

Используйте встроенные функции dir. opendir, readdir и так далее.

http://perldoc.perl.org/functions/opendir.html

http://perldoc.perl.org/functions/readdir.html

person J.J.    schedule 15.10.2008

Чтобы получить вывод системной команды, вам нужно использовать обратные кавычки.

$listing = `ls`;

Однако Perl хорошо справляется с каталогами. Я бы рекомендовал использовать File::Find::Rule.

person holli    schedule 15.10.2008

Используйте Perl Globbing:

my $dir = </dir/path/*> 
person Greg    schedule 05.07.2011

Еще один пример:

chdir $dir or die "Cannot chroot to $dir: $!\n";
my @files = glob("*.txt");
person dynax60    schedule 29.07.2010

РЕДАКТИРОВАТЬ: Упс! Я думал, вам просто нужен список каталогов... удалите вызов "каталог", чтобы этот скрипт делал то, что вы хотите...

На мой взгляд, играть с файловыми дескрипторами - неправильный путь. Ниже приведен пример использования 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);
person Octoberdan    schedule 11.08.2010
comment
+1 как File::Find::Rule качается - person Matthew Lock; 03.12.2012

Я бы порекомендовал вам взглянуть на IPC::Open3. Это позволяет гораздо больше контролировать порожденный процесс, чем система или обратные кавычки.

person dsm    schedule 15.10.2008

В Linux я предпочитаю найти:

my @files = map { chomp; $_ } `find`;
person JDrago    schedule 17.10.2008
comment
это особенно полезно, если вы не просто перечисляете каталог, но хотите найти файлы по некоторым критериям. Например, вы хотите, чтобы файлы были изменены за последние 2 дня: my @recentFiles = map { chomp; $_ } find $theDir -maxdepth 1 -type f -mtime -2; - person Michael Rush; 09.03.2012