7

调查这个问题的行为,我惊讶地发现 perllstat()的每条路径都匹配一个 glob 模式:

$ mkdir dir
$ touch dir/{foo,bar,baz}.txt  
$ strace -e trace=lstat perl -E 'say $^V; <dir/b*>' 
v5.10.1
lstat("dir/baz.txt", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
lstat("dir/bar.txt", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0

我在我的 Linux 系统上使用glob(pattern)and<pattern>和更高版本的 perl 看到了相同的行为。

我的期望是,globbing 将简单地在引擎盖下 opendir/readdir,并且它不需要检查它正在搜索的实际路径名。

这样做的目的是lstat什么?它会影响 glob() 的返回吗?

4

2 回答 2

8

以前在 PerlMonks 上已经注意到这种奇怪的行为。事实证明,支持其标志的glob调用具有以下效果:lstatGLOB_MARK

作为与模式匹配的目录的每个路径名都附加了一个斜杠。

要确定目录条目是否引用子目录,您需要stat它。即使没有给出标志,这显然也是如此。

于 2013-05-09T13:04:46.230 回答
3

我想知道同样的事情 - “这个 lstat 的目的是什么?它会影响 glob() 的返回吗?”

在 bsd_glob.c glob2() 中,我注意到 if 分支中的 g_stat 调用需要设置 GLOB_MARK 标志,我还注意到之前对 g_lstat 的调用没有受到标志检查的保护。当到达模式结束时,两者都在 if 分支内。如果我在 perl-5.12.4/ext/File-Glob/bsd_glob.c 的 glob2 函数中删除这两行

- if (g_lstat(pathbuf, &sb, pglob))
-     return(0);

唯一失败的 perl 测试(make test)是 ext/File-Glob/t/basic.t 中的测试 5:

not ok 5
#   Failed test at ../ext/File-Glob/t/basic.t line 92.
#     Structures begin differing at:
#          $got->[0] = 'asdfasdf'
#     $expected->[0] = Does not exist

t/basic.t 中的测试 5 是

# check nonexistent checks
# should return an empty list
# XXX since errfunc is NULL on win32, this test is not valid there
@a = bsd_glob("asdfasdf", 0);
SKIP: {
    skip $^O, 1 if $^O eq 'MSWin32' || $^O eq 'NetWare';
    is_deeply(\@a, []);
}

如果我将删除的 2 行替换为:

+   if (!((pglob->gl_flags & GLOB_NOCHECK) ||
+         ((pglob->gl_flags & GLOB_NOMAGIC) &&
+          !(pglob->gl_flags & GLOB_MAGCHAR)))){
+     if (g_lstat(pathbuf, &sb, pglob))
+       return(0);
+   }

我没有看到 Linux x86_64 (RHEL6.3 2.6.32-358.11.1.el6.x86_64) 上的 perl-5.12.4 的“make test”有任何失败,并且在使用时:

strace -fe trace=lstat perl -e 'use File::Glob q{:glob};
                               print scalar bsd_glob(q{/var/log/*},GLOB_NOCHECK)'

我不再看到目录中每个文件的 lstat 调用。我并不是说针对 glob (File-Glob) 的 perl 测试是全面的(它们不是),或者这样的更改不会破坏现有行为(这似乎很可能)。据我所知,这个 (g_l)stat 调用的代码在 24 年前的 1990 年存在于 original-bsd/lib/libc/gen/glob.c 中。

另见:

  • Chapter 6. Benchmarking Perl of "Mastering Perl" by brian d foy,Randal L. Schwartz 包含一个比较代码的部分,其中比较了使用 glob() 和 opendir() 的代码。
  • 1991 年 Dick Dunn 的 comp.unix.wizards 中的“future globs (was "UNIX mind...")”。
  • 1986 年 7 月 Guido van Rossum 的 Usenet 新闻组 mod.sources "'Globbing' library routine (glob)" - 我在这段代码中没有看到对 "stat" 的引用。
于 2013-09-10T19:02:00.037 回答