SunOS上linux上的find命令是否有替代方法?


10

findfindSunOS或Solaris上的命令相比,Linux上的命令具有很多选项。

我想使用这样的find命令:

find data/ -type f -name "temp*" -printf "%TY-%Tm-%Td %f\n" | sort -r

它在Linux机器上可以很好地工作,但是在-printfSunOS机器上没有相同的命令。我想以"%TY-%Tm-%Td %f\n"格式自定义输出。

请提出SunOS的其他替代方案。


5
find在Solaris上使用GNU ,请安装findutils软件包。
库沙兰丹

Answers:


21

注意,它与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)


如果GNU人员在实施增强功能之前确实查看了现有标准,那会不会很好?已经存在有关如何使用格式指定ls类型输出的标准,请参见pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html中的
schily

5
@schily,GNU find-printf早POSIX.2,所以POSIX乡亲在这里指责。还要注意,POSIX规范直到2000年代才公开。我仍然要责怪GNU的人,stat在十年后为他们介绍其格式规范时使用了不同而次等的语法。
斯特凡Chazelas

您能提到GNU find何时添加了该功能吗?由于Solaris pax自1998年以来就支持此列表模式,因此我猜它已随SUSv2一起引入。
schily

1
您也可以简单地在自己的bin目录中安装gnu find并设置路径以在规范目录之前进行搜索。
彼得-恢复莫妮卡

@schily,我拥有的最早的GNU版本是1991年的3.1,它已经有了-printf(3.1添加了%k format指令),changelog没有提及何时添加,可能是从一开始就存在的。ChangeLog的历史可以追溯到1987
StéphaneChazelas

0

解决该问题的另一种方法是使用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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.