Có sự thay thế nào cho lệnh `find` trên linux cho SunOS không?


10

Các findlệnh trên Linux có rất nhiều tùy chọn so với findlệnh trên SunOS hoặc Solaris.

Tôi muốn sử dụng findlệnh như thế này:

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

Nó hoạt động hoàn toàn tốt trên máy Linux, nhưng lệnh tương tự không có tùy chọn -printftrên máy SunOS. Tôi muốn tùy chỉnh đầu ra của tôi trong "%TY-%Tm-%Td %f\n"định dạng.

Vui lòng đề xuất bất kỳ lựa chọn thay thế cho SunOS.


5
Để sử dụng GNU findtrên Solaris, hãy cài đặt gói findutils .
Kusalananda

Câu trả lời:


21

Lưu ý rằng nó không liên quan gì đến Linux; -printfvị từ đó là đặc trưng cho việc triển khai GNU find. Linux không phải là HĐH, nó chỉ là hạt nhân được tìm thấy trong một số HĐH. Mặc dù hầu hết các HĐH trước đây thường sử dụng vùng người dùng GNU, nhưng hiện tại, phần lớn các HĐH sử dụng Linux đều được nhúng và có các lệnh cơ bản nếu chúng có.

Lệnh GNU find, có trước Linux, có thể được cài đặt trên hầu hết các HĐH giống Unix. Nó chắc chắn đã được sử dụng trên Solaris (được gọi là SunOS trước đó) trước khi Linux ra đời.

Ngày nay, nó thậm chí còn có sẵn như là một gói Oracle cho Solaris. Trên Solaris 11, đó là file/gnu-findutilsvà lệnh được đặt tên gfind(đối với GNU find, để phân biệt với findlệnh riêng của hệ thống ).

Bây giờ, nếu bạn không thể cài đặt các gói, đặt cược tốt nhất của bạn có lẽ là sử dụng 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

Ở đây, chúng tôi vẫn đang sử dụng find(triển khai Solaris) để tìm các tệp, nhưng chúng tôi đang sử dụng -execvị từ của nó để chuyển danh sách các tệp tới perl. Và perlthực hiện lstat()mỗi lần lấy siêu dữ liệu tệp (bao gồm cả thời gian sửa đổi là phần tử thứ 10 ( $s[9])), diễn giải nó theo múi giờ cục bộ ( localtime()) và định dạng nó ( strftime()) mà sau đó nó nằm printdọc theo tên tệp ( $_là biến vòng lặp nếu không có gì được chỉ định trong perl$!tương đương với stderror(errno)văn bản lỗi cho lỗi cuộc gọi hệ thống cuối cùng).


Sẽ không tốt sao nếu người GNU đã xem xét các tiêu chuẩn hiện có trước khi thực hiện các cải tiến? Đã có một tiêu chuẩn về cách sử dụng định dạng để chỉ định lsđầu ra loại, xem Đặc tả chế độ danh sách trong pubs.opengroup.org/onlinepub/9699919799/utilities/pax.html
schily

5
@schily, GNU find's -printfxảy ra trước POSIX.2, vì vậy các folks POSIX là để đổ lỗi đây. Cũng lưu ý rằng thông số POSIX không được công khai cho đến những năm 2000. Tôi vẫn đổ lỗi cho những người GNU đã giới thiệu stathơn một thập kỷ sau với một cú pháp khác và kém hơn về đặc tả định dạng của nó.
Stéphane Chazelas

Bạn có thể đề cập đến khi GNU find đã thêm tính năng đó không? Vì Solaris pax hỗ trợ chế độ danh sách này từ năm 1998, tôi đoán nó đã được giới thiệu với SUSv2.
schily

1
Bạn cũng có thể chỉ cần cài đặt một tìm kiếm gnu trong thư mục bin của riêng bạn và đặt đường dẫn để tìm kiếm đó trước các thư mục chính tắc.
Peter - Phục hồi Monica

@schily, phiên bản đầu tiên của GNU find tôi có là 3.1 từ năm 1991, nó đã có -printf (3.1 đã thêm chỉ thị định dạng% k), thay đổi không đề cập khi được thêm vào, có thể nó đã có từ đầu. ChangeLog quay trở lại năm 1987.
Stéphane Chazelas

0

Một cách khác để tiếp cận nó là với find2perltập lệnh chuyển đổi (ở đây, một tập hợp con) của findlệnh thành tập lệnh perl tương ứng. Kịch bản perl sử dụng một File::Findmô-đun để thực hiện việc nâng vật nặng. Vì tập lệnh find2perl trên hệ thống của tôi không hỗ trợ -printfvị ngữ, tôi đã thêm nó vào bằng tay:

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

Trên hai tệp mẫu mà tôi đã tạo, đầu ra giống nhau:

$ 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.