快速解决方案
$ ls | perl -lne '打印如果 stat && -f _'
1
2
3
4
5
文件 1
$ ls | perl -lne '打印如果 lstat && -f _'
文件 1
符号链接和查找
默认情况下,GNUfind
从不取消引用或遵循符号链接,但find
文档描述了更改此策略的开关。
控制 find 相对于链接的行为的选项如下:-
-P
find
根本不取消引用符号链接。这是默认行为。此选项必须在命令行上的任何文件名之前指定。
-H
find
不取消引用符号链接(命令行上的文件名被取消引用的情况除外)。如果无法取消引用符号链接,则使用符号链接本身的信息。此选项必须在命令行上的任何文件名之前指定。
-L
find
在可能的情况下取消引用符号链接,在不可能的情况下,它使用符号链接本身的属性。此选项必须在命令行上的任何文件名之前指定。使用此选项也意味着与该选项相同的行为-noleaf
。如果您稍后使用-H
or-P
选项,这不会关闭-noleaf
。
-follow
此选项构成“表达式”的一部分,必须在文件名之后指定,但在其他方面等价于-L
. 该-follow
选项仅影响出现在命令行上的那些测试。此选项已弃用。在可能的情况下,您应该-L
改用。
将查找命令转换为 Perl
标准发行版附带一个与旧 Unix 系统find2perl
兼容的实用程序。find
$ find2perl 。-类型 f | perl
./file1
相反,我们可以要求文件本身是纯文件或指向纯文件的链接。
$ find2perl 。-follow -type f | perl
./1
./2
./3
./4
./5
./file1
在代码生成中,从 File::Find 模块传递给find2perl
的默认子是wanted
find
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
(($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
-f _
&& print("$name\n");
}
但是有了-follow
,我们得到
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
(($dev,$ino,$mode,$nlink,$uid,$gid) = stat($_)) &&
-f _
&& print("$name\n");
}
请注意,唯一的区别是wanted
调用stat
还是lstat
,后者被记录为
lstat EXPR
lstat
与函数执行相同的操作stat
(包括设置特殊_
文件句柄),但统计符号链接而不是符号链接指向的文件。如果您的系统上未实现符号链接,则正常运行stat
。有关更多详细信息,请参阅stat
.
如果省略EXPR$_
,则为 stats 。
正如示例输出所示,您可以使用 filetest 运算符表达您的意图,但可以通过选择vsfind2perl
来精确了解符号链接的语义。stat
lstat
那个有趣的_
令牌
上述_
快速解决方案的末尾是lstat
文档提到的特殊文件句柄。它保存了最新结果的副本,stat
或者lstat
作为避免重复进行那些昂贵的系统调用的一种方式。Filetest 操作符,例如-f
, -r
, -e
,-l
也填充这个缓冲区:
如果任何文件测试(或stat
orlstat
运算符)被赋予由单独下划线组成的特殊文件句柄,则使用前一个文件测试(或stat
运算符)的 stat 结构,保存系统调用。(这不适用于-t
,您需要记住这一点,lstat
并将-l
值保留在符号链接的 stat 结构中,而不是真正的文件中。)(此外,如果 stat 缓冲区被lstat
调用填充,-T
并将-B
重置它的结果stat _
)。例子:
print "Can do.\n" if -r $a || -w _ || -x _;
stat($filename);
print "Readable\n" if -r _;
print "Writable\n" if -w _;
print "Executable\n" if -x _;