快速解决方案
$ ls | perl -lne '打印如果 stat && -f _'
1
2
3
4
5
文件 1
$ ls | perl -lne '打印如果 lstat && -f _'
文件1
符号链接和查找
默认情况下,GNU find 从不取消引用或遵循符号链接,但 find documentation 描述了更改此策略的开关。
控制 find 与链接相关的行为的选项如下:-
-P
find 根本不取消引用符号链接。这是默认行为。此选项必须在命令行上的任何文件名之前指定。
-H
find 不会取消引用符号链接(命令行上的文件名除外,它们会被取消引用)。如果无法取消引用符号链接,则使用符号链接本身的信息。此选项必须在命令行上的任何文件名之前指定。
-L
find 在可能的情况下取消引用符号链接,在不可能的情况下,它使用符号链接本身的属性。此选项必须在命令行上的任何文件名之前指定。使用此选项也意味着与-noleaf 选项相同的行为。如果您稍后使用-H 或-P 选项,这不会关闭-noleaf。
-follow
此选项构成“表达式”的一部分,必须在文件名之后指定,但在其他方面等同于-L。 -follow 选项仅影响出现在命令行上的那些测试。此选项已弃用。如果可能,您应该改用-L。
将查找命令转换为 Perl
标准发行版附带一个 find2perl 实用程序,它与旧 Unix 系统中的 find 兼容。
$ find2perl 。 -类型 f | perl
./file1
我们可以改为要求文件本身是纯文件或指向纯文件的链接。
$ find2perl 。 -follow -type f | perl
./1
./2
./3
./4
./5
./file1
在find2perl生成的代码中,默认wanted子传递给find from the File::Find module是
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 <i>EXPR</i>
lstat
与stat 函数做同样的事情(包括设置特殊的_ 文件句柄)但统计符号链接而不是符号链接指向的文件。如果您的系统上未实现符号链接,则正常的stat 已完成。有关更多详细信息,请参阅stat 的文档。
如果省略EXPR,则统计$_。
正如 find2perl 的示例输出所示,您可以使用 filetest 运算符表达您的意图,但可以通过选择 stat 与 lstat 来准确了解符号链接的语义。
那个有趣的_令牌
上述快速解决方案末尾的_ 是lstat documentation 提到的特殊文件句柄。它保存了来自stat 或lstat 的最新结果的副本,以避免重复进行那些昂贵的系统调用。 Filetest operators 如-f、-r、-e 和-l 也填充此缓冲区:
如果任何文件测试(或stat 或lstat 运算符)被赋予由单独下划线组成的特殊文件句柄,则前一个文件测试(或stat 运算符)的统计结构是使用,保存系统调用。 (这不适用于-t,您需要记住lstat 和-l 将值留在符号链接的统计结构中,而不是真实文件中。)(另外,如果统计缓冲区已满通过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 _;