我即将开始一个可能有一些文件查找和操作的脚本,所以我想我会研究一些对我有帮助的包;大多数情况下,我希望将迭代(或搜索)的结果作为对象返回,这些对象将具有(基本)名称、路径、文件大小、uid、修改时间等作为某种属性。
问题是,我不经常这样做,而且往往会忘记 API;发生这种情况时,我宁愿让代码在示例目录上运行,并将所有属性转储到一个对象中,这样我就可以提醒自己在哪里可用(显然,我想“转储”,以便以避免必须对自定义打印输出进行编码)。但是,我知道以下几点:
列出对象的所有方法 - perlmonks.org
“开箱即用的 Perl 不做对象自省。像 Moose 这样的类包装器提供自省作为其实现的一部分,但 Perl 的内置对象支持远比这更原始。”
无论如何,我调查了:
- “Perl 中的文件和目录处理 - Perl 初学者网站” http://perl-begin.org/topics/files-and-directories/
...并开始查看那里提到的库(还有相关链接:rjbs's rubric: the speed of Perl file finders)。
所以,一方面,File::Find::Object
似乎对我有用;这个片段:
use Data::Dumper;
@targetDirsToScan = ("./");
use File::Find::Object;
my $tree = File::Find::Object->new({}, @targetDirsToScan);
while (my $robh = $tree->next_obj()) {
#print $robh ."\n"; # prints File::Find::Object::Result=HASH(0xa146a58)}
print Dumper($robh) ."\n";
}
...打印这个:
# $VAR1 = bless( {
# 'stat_ret' => [
# 2054,
# 429937,
# 16877,
# 5,
# 1000,
# 1000,
# 0,
# '4096',
# 1405194147,
# 1405194139,
# 1405194139,
# 4096,
# 8
# ],
# 'base' => '.',
# 'is_link' => '',
# 'is_dir' => 1,
# 'path' => '.',
# 'dir_components' => [],
# 'is_file' => ''
# }, 'File::Find::Object::Result' );
# $VAR1 = bless( {
# 'base' => '.',
# 'is_link' => '',
# 'is_dir' => '',
# 'path' => './test.blg',
# 'is_file' => 1,
# 'stat_ret' => [
# 2054,
# 423870,
# 33188,
# 1,
# 1000,
# 1000,
# 0,
# '358',
# 1404972637,
# 1394828707,
# 1394828707,
# 4096,
# 8
# ],
# 'basename' => 'test.blg',
# 'dir_components' => []
...这主要是我想要的,除了stat
结果是一个数组,我必须知道它的布局(($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks)
stat - perldoc.perl.org)才能理解打印输出。
然后我查看了IO::All
,因为 utf-8 处理,我喜欢它(还有,比如说,套接字功能,这对我在同一个脚本中执行不相关的任务很有用);我想我会改用这个包。问题是,我很难发现返回的对象中的可用字段是什么;例如使用此代码:
use Data::Dumper;
@targetDirsToScan = ("./");
use IO::All -utf8;
$io = io(@targetDirsToScan);
@contents = $io->all(0);
for my $contentry ( @contents ) {
#print Dumper($contentry) ."\n";
# $VAR1 = bless( \*Symbol::GEN298, 'IO::All::File' );
# $VAR1 = bless( \*Symbol::GEN307, 'IO::All::Dir' ); ...
#print $contentry->uid . " -/- " . $contentry->mtime . "\n";
# https://stackoverflow.com/q/24717210/printing-ret-of-ioall-w-datadumper
print Dumper \%{*$contentry}; # doesn't list uid
}
...我得到这样的打印输出:
# $VAR1 = {
# '_utf8' => 1,
# 'constructor' => sub { "DUMMY" },
# 'is_open' => 0,
# 'io_handle' => undef,
# 'name' => './test.blg',
# '_encoding' => 'utf8',
# 'package' => 'IO::All'
# };
# $VAR1 = {
# '_utf8' => 1,
# 'constructor' => sub { "DUMMY" },
# 'mode' => undef,
# 'name' => './testdir',
# 'package' => 'IO::All',
# 'is_absolute' => 0,
# 'io_handle' => undef,
# 'is_open' => 0,
# '_assert' => 0,
# '_encoding' => 'utf8'
...这显然不显示诸如mtime
等属性 - 即使它们存在(如果您取消注释相应的打印行,您可以看到)。
我也尝试过Data::Printer
's ( How can I perform introspection in Perl? )p()
功能 - 它打印的字段与Dumper
. 我还尝试使用print Dumper \%{ref ($contentry) . "::"};
(列出对象的所有方法 - perlmonks.org),这会打印出如下内容:
'O_SEQUENTIAL' => *IO::All::File::O_SEQUENTIAL,
'mtime' => *IO::All::File::mtime,
'DESTROY' => *IO::All::File::DESTROY,
...
'deep' => *IO::All::Dir::deep,
'uid' => *IO::All::Dir::uid,
'name' => *IO::All::Dir::name,
...
...但前提是您print $contentry->uid ...
事先使用该行;否则他们没有列出!我想这与此有关:
introspection - 如何在 Perl 中列出给定对象或包的可用方法?#911294
通常,您不能使用像 Perl 这样的动态语言来执行此操作。该包可能定义了一些您可以找到的方法,但它也可以即时组成在您使用它们之前没有定义的方法。此外,即使调用一个方法(有效)也可能不会定义它。这就是使动态语言变得更好的东西。:)
尽管如此,它仍会打印字段的名称和类型——我想要的是字段的名称和值。
所以,我想我的主要问题是 - 我如何转储IO::All
结果,以便所有字段(包括字段stat
)都打印出它们的名称和值(大多数情况下File::Find::Object
)?
(我注意到IO::All
结果可以是类型,比如IO::All::File,但它的文档遵循“See IO::All ”,根本没有IO::All::File
明确讨论。我想,如果我可以“ cast"\%{*$contentry}
到 a IO::All::File
,然后可能mtime
会打印 etc 字段 - 但这样的“演员”可能吗?)
如果这是有问题的,是否有其他软件包可以内省地打印目录迭代结果 - 但对于单个stat
属性有命名字段?