问题描述
这个问题是从这个问题衍生出来的一个.一些历史:当我第一次学习 Perl 时,我几乎总是使用 glob
而不是 opendir
+ readdir
因为我发现它更容易.后来各种帖子和阅读都表明 glob
很糟糕,所以现在我几乎总是使用 readdir
.
This question is a spin-off from this one. Some history: when I first learned Perl, I pretty much always used glob
rather than opendir
+ readdir
because I found it easier. Then later various posts and readings suggested that glob
was bad, and so now I pretty much always use readdir
.
在考虑这个最近的问题后 我意识到我选择其中一个的理由可能是胡说八道.所以,我将列出一些优点和缺点,我希望更有经验的 Perl 人能够插话并澄清.简而言之,问题是是否有令人信服的理由更喜欢 glob
到 readdir
或 readdir
到 glob
(在某些情况下)或所有情况)?
After thinking over this recent question I realized that my reasons for one or the other choice may be bunk. So, I'm going to lay out some pros and cons, and I'm hoping that more experienced Perl folks can chime in and clarify. The question in a nutshell is are there compelling reasons to prefer glob
to readdir
or readdir
to glob
(in some or all cases)?
- 没有点文件(除非你要求)
- 保证商品的顺序
- 无需手动将目录名称添加到项目中
- 更好的名字(来吧 -
glob
与readdir
对比,如果我们仅凭名字来判断的话) (来自 ysth 的回答;参见下面的
glob
cons 4)可以返回不存在的文件名:
- No dotfiles (unless you ask for them)
- Order of items is guaranteed
- No need to prepend the directory name onto items manually
- Better name (c'mon -
glob
versusreaddir
is no contest if we're judging by names alone) (From ysth's answer; cf.
glob
cons 4 below) Can return non-existent filenames:
@deck = glob "{A,K,Q,J,10,9,8,7,6,5,4,3,2}{x{2660},x{2665},x{2666},x{2663}}";
glob
缺点:
- 旧版本只是简单的损坏(但旧"意味着 5.6 之前的版本,我认为,坦率地说,如果您使用的是 5.6 之前的 Perl,您会遇到更大的问题)
- 每次都调用
stat
(即在大多数情况下无用地使用stat
). - 目录名称中的空格问题(是否仍然如此?)
(来自 brian 的回答)可以返回不存在的文件名:
- Older versions are just plain broken (but 'older' means pre 5.6, I think, and frankly if you're using pre 5.6 Perl, you have bigger problems)
- Calls
stat
each time (i.e., useless use ofstat
in most cases). - Problems with spaces in directory names (is this still true?)
(From brian's answer) Can return filenames that don't exist:
$ perl -le 'print glob "{ab}{cd}"'
readdir
优点:
- (来自 brian 的回答)
opendir
返回一个文件句柄,您可以在程序中传递它(并重用),但glob
只返回一个列表 - (来自 brian 的回答)
readdir
是一个合适的迭代器,并为rewinddir
、seekdir
、telldir
提供函数 - 更快?(纯粹基于上述
glob
的一些特性的猜测.无论如何,我并不真正担心这种级别的优化,但它是一个理论上的专家.) - 比
glob
更不容易出现边缘情况错误? - 默认读取所有内容(也包括点文件)(这也是一个缺点)
- 可能会说服您不要将文件命名为
0
(也是一个骗局 - 请参阅 Brad 的回答) - 有人吗?布勒?布勒?
- (From brian's answer)
opendir
returns a filehandle which you can pass around in your program (and reuse), butglob
simply returns a list - (From brian's answer)
readdir
is a proper iterator and provides functions torewinddir
,seekdir
,telldir
- Faster? (Pure guess based on some of
glob
's features from above. I'm not really worried about this level of optimization anyhow, but it's a theoretical pro.) - Less prone to edge-case bugs than
glob
? - Reads everything (dotfiles too) by default (this is also a con)
- May convince you not to name a file
0
(a con also - see Brad's answer) - Anyone? Bueller? Bueller?
readdir
缺点:
- 如果您不记得在目录名前面加上,当您尝试执行文件测试或复制项目或编辑项目或...
- 如果您不记得
grep
.
和..
项,您会得到当你计算项目时,或者尝试递归地沿着文件树向下走或者...... - 我有没有提到在目录名之前加上?(旁注,但我在 Perl 初学者邮件列表上的第一篇文章是经典的,为什么这段涉及文件测试的代码有时不起作用?"与这个陷阱相关的问题.显然,我仍然很痛苦.)
- 物品的返回没有特定的顺序.这意味着您经常必须记住以某种方式对它们进行排序.(如果这意味着更快的速度,并且这意味着您实际上考虑如何以及是否需要对项目进行排序,那么这可能是一个专业人士.)编辑:非常小的样本,但在 Mac 上
readdir
按字母顺序返回项目,不区分大小写.在 Debian 机器和 OpenBSD 服务器上,顺序是完全随机的.我使用 Apple 的内置 Perl (5.8.8) 和我自己编译的 5.10.1 测试了 Mac.Debian 机器是 5.10.0,OpenBSD 机器也是.我想知道这是否是文件系统问题,而不是 Perl? - 默认读取所有内容(也包括点文件)(这也是专业人士)
- 不一定能很好地处理名为
0
的文件(另请参阅专业人士 - 请参阅 Brad 的回答)
- If you don't remember to prepend the directory name, you will get bit when you try to do filetests or copy items or edit items or...
- If you don't remember to
grep
out the.
and..
items, you will get bit when you count items, or try to walk recursively down the file tree or... - Did I mention prepending the directory name? (A sidenote, but my very first post to the Perl Beginners mail list was the classic, "Why does this code involving filetests not work some of the time?" problem related to this gotcha. Apparently, I'm still bitter.)
- Items are returned in no particular order. This means you will often have to remember to sort them in some manner. (This could be a pro if it means more speed, and if it means that you actually think about how and if you need to sort items.) Edit: Horrifically small sample, but on a Mac
readdir
returns items in alphabetical order, case insensitive. On a Debian box and an OpenBSD server, the order is utterly random. I tested the Mac with Apple's built-in Perl (5.8.8) and my own compiled 5.10.1. The Debian box is 5.10.0, as is the OpenBSD machine. I wonder if this is a filesystem issue, rather than Perl? - Reads everything (dotfiles too) by default (this is also a pro)
- Doesn't necessarily deal well with a file named
0
(see pros also - see Brad's answer)
推荐答案
你错过了它们之间最重要、最大的区别:glob
给你一个列表,但是 opendir
给你一个目录句柄.您可以传递该目录句柄以让其他对象或子例程使用它.有了目录句柄,子程序或对象就不必知道它来自哪里,还有谁在使用它,等等:
You missed the most important, biggest difference between them: glob
gives you back a list, but opendir
gives you a directory handle. You can pass that directory handle around to let other objects or subroutines use it. With the directory handle, the subroutine or object doesn't have to know anything about where it came from, who else is using it, and so on:
sub use_any_dir_handle {
my( $dh ) = @_;
rewinddir $dh;
...do some filtering...
return @files;
}
使用目录句柄,您有一个可控迭代器,您可以在其中使用 seekdir
四处移动,尽管使用 glob
您只会得到下一个项目.
With the dirhandle, you have a controllable iterator where you can move around with seekdir
, although with glob
you just get the next item.
与任何事情一样,成本和收益只有在应用于特定环境时才有意义.它们不存在于特定用途之外.您有一个很好的差异列表,但我不会在不知道您试图用它们做什么的情况下对这些差异进行分类.
As with anything though, the costs and benefits only make sense when applied to a certain context. They do not exist outside of a particular use. You have an excellent list of their differences, but I wouldn't classify those differences without knowing what you were trying to do with them.
要记住的其他一些事情:
Some other things to remember:
您可以使用
opendir
实现您自己的 glob,但反过来不行.
You can implement your own glob with
opendir
, but not the other way around.
glob 使用它自己的通配符语法,这就是你所得到的.
glob uses its own wildcard syntax, and that's all you get.
glob 可以返回不存在的文件名:
glob can return filenames that don't exist:
$ perl -le 'print glob "{ab}{cd}"'
这篇关于在 Perl 中,有什么理由更喜欢 glob 而不是 readdir(或反之亦然)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!