web-dev-qa-db-ja.com

LinuxでSunOSの `find`コマンドに代わるものはありますか?

Linuxのfindコマンドには、SunOSまたはSolarisのfindコマンドと比較して多くのオプションがあります。

次のようにfindコマンドを使用したい:

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

Linuxマシンでは問題なく動作しますが、SunOSマシンでは同じコマンドに-printfオプションがありません。出力を"%TY-%Tm-%Td %f\n"形式でカスタマイズしたい。

SunOSの代替案を提案してください。

10
Pratik Mayekar

Linuxとは何の関係もないことに注意してください。その_-printf_述語は、GNU findの実装に固有です。LinuxはOSではなく、多くのOSで見られるカーネルにすぎません。これらのOSのほとんどは、 a GNU以前はユーザーランドでしたが、今ではLinuxを使用するOSの大部分が組み込まれており、基本的なコマンドがあればそれを持っています。

Linuxより前のGNU findコマンドは、ほとんどのUnixライクなOSにインストールできます。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()を実行して、ファイルのメタデータ(変更時刻を10番目の要素(_$s[9]_)として含む)を取得し、ローカルタイムゾーンで解釈します(localtime() )そしてそれをフォーマットします(strftime())これをファイル名と一緒にprints(_$__はPerlで何も指定されていない場合ループ変数であり、_$!_はstderror(errno)、最後のシステムコールエラーのエラーテキスト)。

21

これに取り組む別の方法は、findコマンドの(ここではサブセット)を対応するPerlスクリプトに変換するfind2Perlスクリプトを使用することです。 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;

私が作成した2つのサンプルファイルでは、出力は同じです。

$ 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
0
Jeff Schaller