迭代Perl中的目录,获得内省对象的结果 [英] Iterate directories in Perl, getting introspectable objects as result

查看:174
本文介绍了迭代Perl中的目录,获得内省对象的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我即将启动一个可能有一些文件查找和操作的脚本,所以我想我会查看一些可以帮助我的软件包;大多数情况下,我希望将迭代(或搜索)的结果作为对象返回,这些对象具有(基本)名称,路径,文件大小,uid,修改时间等作为某种属性。

I'm about to start a script that may have some file lookups and manipulation, so I thought I'd look into some packages that would assist me; mostly, I'd like the results of the iteration (or search) to be returned as objects, which would have (base)name, path, file size, uid, modification time, etc as some sort of properties.

事情是,我不经常这样做,而且往往会忘记API;当发生这种情况时,我宁愿让代码在一个示例目录上运行,并将所有属性转储到一个对象中,这样我就可以提醒自己哪些可用(显然,我想转储,按顺序避免必须编写自定义打印输出)。但是,我知道以下内容:

The thing is, I don't do this all that often, and tend to forget APIs; when that happens, I'd rather let the code run on an example directory, and dump all of the properties in an object, so I can remind myself what is available where (obviously, I'd like to "dump", in order to avoid having to code custom printouts). However, I'm aware of the following:


列出对象的所有方法 - perlmonks.org

开箱即用Perl不进行对象内省。像Moose这样的类包装器提供内省作为其实现的一部分,但Perl内置的对象支持比原始内容更原始。

list out all methods of object - perlmonks.org
"Out of the box Perl doesn't do object introspection. Class wrappers like Moose provide introspection as part of their implementation, but Perl's built in object support is much more primitive than that."

无论如何,我调查了:

Anyways, I looked into:

  • "Files and Directories Handling in Perl - Perl Beginners' Site" http://perl-begin.org/topics/files-and-directories/

...并开始调查那里提到的图书馆(也是相关链接: rjbs的标题:Perl文件查找器的速度)。

... and started looking into the libraries referred there (also related link: rjbs's rubric: the speed of Perl file finders).

所以,对于一个, File :: Find :: Object 似乎对我有用;这个片段:

So, for one, File::Find::Object seems to work for me; this snippet:

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 )了解打印输出。

... which is mostly what I wanted, except the stat results are an array, and I'd have to know its layout (($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) stat - perldoc.perl.org) to make sense of the printout.

然后我查看 IO ::所有,我喜欢因为utf-8处理(但也就是说,套接字功能,这对我来说对同一个脚本中不相关的任务很有用);而我以为我会用这个包代替。问题是,我很难发现返回的对象中的可用字段是什么;例如使用此代码:

Then I looked into IO::All, which I like because of utf-8 handling (but also, say, socket functionality, which would be useful to me for an unrelated task in the same script); and I was thinking I'd use this package instead. The problem is, I have a very hard time discovering what the available fields in the object returned are; e.g. with this code:

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
}

...我得到这样的打印输出:

... I get a printout like this:

# $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这样的属性等 - 即使它们存在(如果您取消注释相应的打印行,也可以看到)。

... which clearly doesn't show attributes like mtime, etc. - even if they exist (which you can see if you uncomment the respective print line).

我也试过数据::打印机的(如何在Perl中执行内省? p() function - 它打印的字段与 Dumper完全相同。我还尝试使用 print Dumper \%{ref($ contentry)。 ::}; 列出所有对象方法 - perlmonks.org ),这打印的内容如下:

I've also tried Data::Printer's (How can I perform introspection in Perl?) p() function - it prints exactly the same fields as Dumper. I also tried to use print Dumper \%{ref ($contentry) . "::"}; (list out all methods of object - perlmonks.org), and this prints stuff like:

'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 ... 行;否则他们没有列出!我猜这与此有关:

... but only if you use the print $contentry->uid ... line beforehand; else they are not listed! I guess that relates to this:


introspection - 如何列出Perl中给定对象或包的可用方法? #911294

一般来说,你不能用像Perl这样的动态语言来做到这一点。该软件包可能会定义一些您可以找到的方法,但它们也可以在您使用它们之前动态地组成没有定义的方法。此外,即使调用方法(有效)也可能无法定义它。这就是使动态语言变得美好的东西。 :)

introspection - How do I list available methods on a given object or package in Perl? #911294
In general, you can't do this with a dynamic language like Perl. The package might define some methods that you can find, but it can also make up methods on the fly that don't have definitions until you use them. Additionally, even calling a method (that works) might not define it. That's the sort of things that make dynamic languages nice. :)

仍然,打印字段的名称和类型 - 我想要字段的名称和值。

Still, that prints the name and type of the field - I'd want the name and value of the field instead.

所以,我想我的主要问题是 - 如何转储 IO :: All 结果,以便打印出所有字段(包括 stat 的字段)及其名称和值(大多数情况下是 File :: Find :: Object )?

So, I guess my main question is - how can I dump an IO::All result, so that all fields (including stat ones) are printed out with their names and values (as is mostly the case with File::Find::Object)?

(我注意到 IO :: All 结果可以是类型,比如说, IO :: All :: File ,但其文档推迟到请参阅 IO ::全部,它没有明确地讨论 IO :: All :: File 。我想,如果我可以施放 \%{* $ contentry} IO :: All :: File ,也许 mtime 等字段将被打印 - 但是这样的演员是可能的?)

(I noticed the IO::All results can be of type, say, IO::All::File, but its docs defer to "See IO::All", which doesn't discuss IO::All::File explicitly much at all. I thought, if I could "cast" \%{*$contentry} to a IO::All::File, maybe then mtime etc fields will be printed - but is such a "cast" possible at all?)

如果这有问题,是否有其他软件包,允许内省打印输出目录迭代结果 - 但是使用个别 stat的命名字段属性?

If that is problematic, are there other packages, that would allow introspective printout of directory iteration results - but with named fields for individual stat properties?

推荐答案

当我回答你上一个问题时,不是一个好主意去依靠Perl中的对象内容。而只是调用方法。

As I answered to your previous question, it is not a good idea to go relying on the guts of objects in Perl. Instead just call methods.

如果IO :: All没有提供一个方法来提供您需要的信息,那么您可以编写自己的方法只使用IO :: All提供的文档化方法组装该信息...

If IO::All doesn't offer a method that gives you the information that you need, you might be able to write your own method for it that assembles that information using just the documented methods provided by IO::All...

use IO::All;

# Define a new method for IO::All::Base to use, but
# define it in a lexical variable!
#
my $dump_info = sub {
   use Data::Dumper ();
   my $self = shift;
   local $Data::Dumper::Terse    = 1;
   local $Data::Dumper::Sortkeys = 1;
   return Data::Dumper::Dumper {
      name    => $self->name,
      mtime   => $self->mtime,
      mode    => $self->mode,
      ctime   => $self->ctime,
   };
};

$io = io('/tmp');
for my $file ( $io->all(0) ) {
   print $file->$dump_info();
}

这篇关于迭代Perl中的目录,获得内省对象的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆