find
与find
SunOS或Solaris上的命令相比,Linux上的命令具有很多选项。
我想使用这样的find
命令:
find data/ -type f -name "temp*" -printf "%TY-%Tm-%Td %f\n" | sort -r
它在Linux机器上可以很好地工作,但是在-printf
SunOS机器上没有相同的命令。我想以"%TY-%Tm-%Td %f\n"
格式自定义输出。
请提出SunOS的其他替代方案。
find
与find
SunOS或Solaris上的命令相比,Linux上的命令具有很多选项。
我想使用这样的find
命令:
find data/ -type f -name "temp*" -printf "%TY-%Tm-%Td %f\n" | sort -r
它在Linux机器上可以很好地工作,但是在-printf
SunOS机器上没有相同的命令。我想以"%TY-%Tm-%Td %f\n"
格式自定义输出。
请提出SunOS的其他替代方案。
Answers:
注意,它与Linux无关。该-printf
谓词特定于GNU的GNU实现find
。Linux不是操作系统,它只是许多操作系统中的内核。虽然过去大多数操作系统曾经使用GNU用户区,但是现在大多数使用Linux的操作系统都是嵌入式的,并且具有基本命令(如果有)。
find
早于Linux 的GNU 命令可以安装在大多数类似Unix的操作系统上。在Linux出现之前,它肯定已在Solaris(此后称为SunOS)上使用。
如今,它甚至可以作为Solaris的Oracle软件包使用。在Solaris 11上,它位于中file/gnu-findutils
,并且命令名称被命名gfind
(对于GNU来说find
,是为了将其与系统自己的find
命令区分开来)。
现在,如果您无法安装软件包,最好的选择是使用perl
:
find data/ -type f -name "temp*" -exec perl -MPOSIX -le '
for (@ARGV) {
unless(@s = lstat($_)) {
warn "$_: $!\n";
next;
}
print strftime("%Y-%m-%d", localtime($s[9])) . " $_";
}' {} + | sort -r
在这里,我们仍在使用find
(Solaris实现)查找文件,但是我们使用其-exec
谓词将文件列表传递给perl
。并对每个元数据perl
执行一次操作lstat()
,以检索文件元数据(包括作为第十个元素的修改时间($s[9]
)),在本地时区(localtime()
)对其进行解释,并对其进行格式设置(strftime()
),然后将其print
与文件名一起存储($_
如果为循环变量,则为循环变量在上一次系统调用失败的错误文本中perl
,没有指定,并且$!
与等效stderror(errno)
。
ls
类型输出的标准,请参见pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html中的
find
的-printf
早POSIX.2,所以POSIX乡亲在这里指责。还要注意,POSIX规范直到2000年代才公开。我仍然要责怪GNU的人,stat
在十年后为他们介绍其格式规范时使用了不同而次等的语法。
解决该问题的另一种方法是使用find2perl
脚本,该脚本将命令(这里是子集)转换find
为相应的perl脚本。perl脚本使用一个File::Find
模块来完成繁重的工作。由于我系统上的find2perl脚本不支持该-printf
谓词,因此我手动添加了它:
#! /usr/bin/perl -w
use strict;
use File::Find ();
use vars qw/*name *dir *prune/;
*name = *File::Find::name;
*dir = *File::Find::dir;
*prune = *File::Find::prune;
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid, $mtime, $year, $month, $day);
if ((($dev,$ino,$mode,$nlink,$uid,$gid,undef,undef,undef,$mtime) = lstat($_)) &&
-f _ &&
/^temp.*\z/s) {
(undef, undef, undef, $day, $month, $year) = localtime($mtime);
$year += 1900;
$month++;
printf "%d-%d-%d %s\n", $year, $month, $day, $_;
}
}
File::Find::find({wanted => \&wanted}, 'data/');
exit;
在我创建的两个示例文件上,输出是相同的:
$ tree data
data
├── subdir
│ └── foo
│ └── temp2
└── temp1
2 directories, 2 files
$ touch -d 2018-06-20 data/subdir/foo/temp2
$ touch -d 2018-05-19 data/temp1
$ find data/ -type f -name "temp*" -printf "%TY-%Tm-%Td %f\n" | sort -r
2018-06-20 temp2
2018-05-19 temp1
$ ./perlfind | sort -r
2018-06-20 temp2
2018-05-19 temp1
find
在Solaris上使用GNU ,请安装findutils软件包。