Looking into behavior in this question, I was surprised to see that perl lstat()
s every path matching a glob pattern:
在这个问题中查看行为,我很惊讶地看到perl lstat()的每个路径都与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
I see the same behavior on my Linux system with glob(pattern)
and <pattern>
, and with later versions of perl.
我在我的Linux系统上看到了与glob(模式)和
My expectation was that the globbing would simply opendir/readdir under the hood, and that it would not need to inspect the actual pathnames it was searching.
我的期望是,globbing只是opendir / readdir,并且它不需要检查它正在搜索的实际路径名。
What is the purpose of this lstat
? Does it affect the glob()s return?
这个lstat的目的是什么?它会影响glob()的返回吗?
2 个解决方案
#1
8
This strange behavior has been noticed before on PerlMonks. It turns out that glob
calls lstat
to support its GLOB_MARK
flag, which has the effect that:
之前在PerlMonks上已经注意到这种奇怪的行为。事实证明,glob调用lstat来支持它的GLOB_MARK标志,其结果是:
Each pathname that is a directory that matches the pattern has a slash appended.
作为与模式匹配的目录的每个路径名都附加了一个斜杠。
To find out whether a directory entry refers to a subdir, you need to stat
it. This is apparently done even when the flag is not given.
要确定目录条目是否引用了子目录,您需要对其进行统计。即使没有给出标志,这显然已经完成。
#2
2
I was wondering the same thing - "What is the purpose of this lstat? Does it affect the glob()s return?"
我想知道同样的事情 - “这个lstat的目的是什么?它会影响glob()的返回吗?”
Within bsd_glob.c glob2() I noticed a g_stat call within an if branch that required the GLOB_MARK flag to be set, I also noticed a call to g_lstat just before that was not guarded by a flag check. Both are within an if branch for when the end of pattern is reached. If I remove these 2 lines in the glob2 function in perl-5.12.4/ext/File-Glob/bsd_glob.c
在bsd_glob.c glob2()中,我注意到在if分支中需要设置GLOB_MARK标志的g_stat调用,我还注意到在没有被标志检查保护之前调用g_lstat。当达到模式结束时,两者都在if分支内。如果我在perl-5.12.4 / ext / File-Glob / bsd_glob.c中的glob2函数中删除这两行
- if (g_lstat(pathbuf, &sb, pglob))
- return(0);
the only perl test (make test) that fails is test 5 in ext/File-Glob/t/basic.t with:
唯一失败的perl测试(make test)是ext / File-Glob / t / basic.t中的test 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
Test 5 in t/basic.t is
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, []);
}
If I replace the 2 lines removed with:
如果我用以下内容替换掉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);
+ }
I don't see any failures from "make test" for perl-5.12.4 on linux x86_64 (RHEL6.3 2.6.32-358.11.1.el6.x86_64) and when using:
我没有在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)'
I no longer see the lstat calls for each file in the dir. I don't mean to suggest that the perl tests for glob (File-Glob) are comprehensive (they are not), or that a change such as this will not break existing behaviour (this seems likely). As far as I can tell the code with this (g_l)stat call existed in original-bsd/lib/libc/gen/glob.c 24 years ago in 1990.
我不再在dir中看到每个文件的lstat调用。我并不是说建议对glob(File-Glob)的perl测试是全面的(它们不是),或者像这样的更改不会破坏现有行为(这似乎很可能)。据我所知,这个(g_l)stat调用的代码存在于原始-bsd / lib / libc / gen / glob.c 24年前的1990年。
Also see:
- Chapter 6. Benchmarking Perl of "Mastering Perl" By brian d foy, Randal L. Schwartz contains a section on comparing code where code using glob() and opendir() is compared.
- "future globs (was "UNIX mindset...")" in comp.unix.wizards from Dick Dunn in 1991.
- Usenet newsgroup mod.sources "'Globbing' library routine (glob)" from Guido van Rossum in July 1986 - I don't see a reference to "stat" in this code.
第6章“掌握Perl”的Perl标记作者:brian d foy,Randal L. Schwartz包含一个比较代码的部分,其中比较了使用glob()和opendir()的代码。
1991年,来自Dick Dunn的comp.unix.wizards中的“未来的全球(是”UNIX心态......“)”。
1986年7月来自Guido van Rossum的Usenet新闻组mod.sources“'Globbing'库例程(glob)” - 我在这段代码中没有看到“stat”的引用。
#1
8
This strange behavior has been noticed before on PerlMonks. It turns out that glob
calls lstat
to support its GLOB_MARK
flag, which has the effect that:
之前在PerlMonks上已经注意到这种奇怪的行为。事实证明,glob调用lstat来支持它的GLOB_MARK标志,其结果是:
Each pathname that is a directory that matches the pattern has a slash appended.
作为与模式匹配的目录的每个路径名都附加了一个斜杠。
To find out whether a directory entry refers to a subdir, you need to stat
it. This is apparently done even when the flag is not given.
要确定目录条目是否引用了子目录,您需要对其进行统计。即使没有给出标志,这显然已经完成。
#2
2
I was wondering the same thing - "What is the purpose of this lstat? Does it affect the glob()s return?"
我想知道同样的事情 - “这个lstat的目的是什么?它会影响glob()的返回吗?”
Within bsd_glob.c glob2() I noticed a g_stat call within an if branch that required the GLOB_MARK flag to be set, I also noticed a call to g_lstat just before that was not guarded by a flag check. Both are within an if branch for when the end of pattern is reached. If I remove these 2 lines in the glob2 function in perl-5.12.4/ext/File-Glob/bsd_glob.c
在bsd_glob.c glob2()中,我注意到在if分支中需要设置GLOB_MARK标志的g_stat调用,我还注意到在没有被标志检查保护之前调用g_lstat。当达到模式结束时,两者都在if分支内。如果我在perl-5.12.4 / ext / File-Glob / bsd_glob.c中的glob2函数中删除这两行
- if (g_lstat(pathbuf, &sb, pglob))
- return(0);
the only perl test (make test) that fails is test 5 in ext/File-Glob/t/basic.t with:
唯一失败的perl测试(make test)是ext / File-Glob / t / basic.t中的test 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
Test 5 in t/basic.t is
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, []);
}
If I replace the 2 lines removed with:
如果我用以下内容替换掉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);
+ }
I don't see any failures from "make test" for perl-5.12.4 on linux x86_64 (RHEL6.3 2.6.32-358.11.1.el6.x86_64) and when using:
我没有在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)'
I no longer see the lstat calls for each file in the dir. I don't mean to suggest that the perl tests for glob (File-Glob) are comprehensive (they are not), or that a change such as this will not break existing behaviour (this seems likely). As far as I can tell the code with this (g_l)stat call existed in original-bsd/lib/libc/gen/glob.c 24 years ago in 1990.
我不再在dir中看到每个文件的lstat调用。我并不是说建议对glob(File-Glob)的perl测试是全面的(它们不是),或者像这样的更改不会破坏现有行为(这似乎很可能)。据我所知,这个(g_l)stat调用的代码存在于原始-bsd / lib / libc / gen / glob.c 24年前的1990年。
Also see:
- Chapter 6. Benchmarking Perl of "Mastering Perl" By brian d foy, Randal L. Schwartz contains a section on comparing code where code using glob() and opendir() is compared.
- "future globs (was "UNIX mindset...")" in comp.unix.wizards from Dick Dunn in 1991.
- Usenet newsgroup mod.sources "'Globbing' library routine (glob)" from Guido van Rossum in July 1986 - I don't see a reference to "stat" in this code.
第6章“掌握Perl”的Perl标记作者:brian d foy,Randal L. Schwartz包含一个比较代码的部分,其中比较了使用glob()和opendir()的代码。
1991年,来自Dick Dunn的comp.unix.wizards中的“未来的全球(是”UNIX心态......“)”。
1986年7月来自Guido van Rossum的Usenet新闻组mod.sources“'Globbing'库例程(glob)” - 我在这段代码中没有看到“stat”的引用。