Чи є альтернативи команді `find` на linux для SunOS?


10

findКоманда на Linux має багато варіантів по порівнянні з findкомандою на SunOS або Solaris.

Я хочу використовувати findкоманду так:

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

Він працює чудово на машині Linux, але ця ж команда не має можливості -printfна машині SunOS. Я хочу налаштувати свій вихід у "%TY-%Tm-%Td %f\n"форматі.

Запропонуйте будь-які альтернативи для SunOS.


5
Щоб використовувати GNU findна Solaris, встановіть пакет findutils .
Кусалаланда

Відповіді:


21

Зауважте, що це не має нічого спільного з Linux; цей -printfпредикат є специфічним для реалізації GNU find. Linux - це не ОС, це лише ядро, яке знаходиться в багатьох ОС. У той час як більшість цих ОС раніше використовували землю користувачів GNU, тепер переважна більшість ОС, що використовують Linux, є вбудованими та мають базові команди, якщо вони є.

Команда GNU find, яка передує Linux, може бути встановлена ​​на більшості Unix-подібних ОС. Він, безумовно, використовувався на Solaris (тоді він називався SunOS) до появи Linux.

На сьогоднішній день він навіть доступний як пакет Oracle для Solaris. На 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робить a lstat()на кожному, щоб отримати метадані файлу (включаючи час модифікації як 10-й елемент ( $s[9])), інтерпретує його у локальному часовому поясі ( localtime()) та форматує його ( strftime()), який він потім розташовує printпоряд з ім'ям файлу ( $_є змінною циклу, якщо жоден з них не вказаний у тексті помилки для останньої помилки системного виклику perlі $!є еквівалентом stderror(errno).


Не було б непогано, якби люди GNU вивчали існуючі стандарти, перш ніж впроваджувати удосконалення? Вже є стандарт про те, як використовувати формат для визначення lsтипу виводу, див. Специфікація режиму списку в pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
schily

5
@schily, GNU find«s -printfпередує POSIX.2, так що люди POSIX винні тут. Також зауважте, що специфікація POSIX не була загальнодоступною до 2000-х. Я все ще звинувачую людей у ​​GNU за те, що вони представили їх statчерез десятиліття пізніше з іншим і неповноцінним синтаксисом для його специфікації формату.
Стефан Шазелас

Не могли б ви згадати, коли GNU знайшов додав цю функцію? Оскільки Solaris pax підтримує цей режим списку з 1998 року, я думаю, він був представлений із SUSv2.
шилі

1
Ви також можете просто встановити знахідку gnu у власному каталозі бін та встановити шлях для пошуку, який знаходиться перед канонічними каталогами.
Пітер - Відновіть Моніку

@schily, найдавніша версія GNU, яку я маю, - 3.1 з 1991 року, вона вже мала -printf (3.1 додала директиву про формат% k), журнал змін не згадує, коли він був доданий, можливо, він був там із самого початку. ChangeLog бере свій початок у 1987 році.
Стефан Шазелас

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.