Apakah ada alternatif untuk perintah `find` di linux untuk SunOS?

10

The findperintah pada Linux memiliki banyak pilihan dibandingkan dengan findperintah pada SunOS atau Solaris.

Saya ingin menggunakan findperintah seperti ini:

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

Ini berfungsi dengan baik pada mesin Linux, tetapi perintah yang sama tidak memiliki opsi -printfpada mesin SunOS. Saya ingin menyesuaikan output saya dalam "%TY-%Tm-%Td %f\n"format.

Harap sarankan alternatif untuk SunOS.

Pratik Mayekar
sumber
5
Untuk menggunakan GNU findpada Solaris, instal paket findutils .
Kusalananda

Jawaban:

21

Perhatikan bahwa tidak ada hubungannya dengan Linux; bahwa -printfpredikat khusus untuk pelaksanaan GNU dari find. Linux bukan OS, itu hanya kernel yang ditemukan di sejumlah OS. Sementara sebagian besar OS yang digunakan untuk menggunakan GNU userland di masa lalu, sekarang sebagian besar OS menggunakan Linux tertanam dan memiliki perintah dasar jika mereka memilikinya.

findPerintah GNU , yang mendahului Linux, dapat diinstal pada sebagian besar OS mirip Unix. Itu pasti digunakan pada Solaris (disebut SunOS saat itu) sebelum Linux keluar.

Saat ini, bahkan tersedia sebagai paket Oracle untuk Solaris. Pada Solaris 11, itu dalam file/gnu-findutils, dan perintah itu dinamai gfind(untuk GNU find, untuk membedakannya dari perintah sistem itu sendiri find).

Sekarang, jika Anda tidak dapat menginstal paket, kemungkinan terbaik Anda adalah menggunakan 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

Di sini, kami masih menggunakan find(implementasi Solaris) untuk menemukan file, tetapi kami menggunakan -execpredikatnya untuk meneruskan daftar file perl. Dan perlmelakukan a lstat()pada masing-masing untuk mengambil metadata file (termasuk waktu modifikasi sebagai elemen ke-10 ( $s[9])), menafsirkannya dalam zona waktu lokal ( localtime()) dan memformatnya ( strftime()) yang kemudian printbersama dengan nama file ( $_adalah variabel loop jika tidak ada yang ditentukan dalam perl, dan $!setara dengan stderror(errno), teks kesalahan untuk kegagalan panggilan sistem terakhir).

Stéphane Chazelas
sumber
Bukankah lebih baik jika orang-orang GNU melihat standar yang ada sebelum mengimplementasikan peningkatan? Sudah ada standar tentang cara menggunakan format untuk menentukan lstipe keluaran, lihat Spesifikasi mode daftar di pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
schily
5
@schily, GNU find's -printfmendahului POSIX.2, sehingga orang-orang POSIX yang harus disalahkan di sini. Perhatikan juga bahwa spesifikasi POSIX belum dipublikasikan hingga tahun 2000-an. Saya masih menyalahkan orang-orang GNU untuk memperkenalkan mereka statlebih dari satu dekade kemudian dengan sintaks yang berbeda dan lebih rendah untuk spesifikasi formatnya.
Stéphane Chazelas
Bisakah Anda menyebutkan kapan GNU menemukan menambahkan fitur itu? Karena Solaris pax mendukung mode daftar ini sejak 1998, saya kira itu telah diperkenalkan dengan SUSv2.
schily
1
Anda juga bisa menginstal gnu find di direktori bin Anda sendiri dan mengatur path untuk mencari sebelum direktori kanonik.
Peter - Reinstate Monica
@schily, versi GNU yang paling awal saya temukan adalah 3.1 dari 1991, sudah ada -printf (3.1 menambahkan direktif format% k), changelog tidak menyebutkan kapan ditambahkan, mungkin ada di sana sejak awal. The ChangeLog kembali ke 1987.
Stéphane Chazelas
0

Cara lain untuk mendekatinya adalah dengan find2perlskrip, yang mengubah (di sini, subset) dari sebuah findperintah ke skrip perl yang sesuai. Skrip perl menggunakan File::Findmodul untuk melakukan pengangkatan berat. Karena skrip find2perl di sistem saya tidak mendukung -printfpredikat, saya menambahkannya secara manual:

#! /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;

Pada dua file sampel yang saya buat, hasilnya sama:

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