Czy są jakieś alternatywy dla polecenia `find` w systemie Linux dla SunOS?


10

findPoleceń w systemie Linux ma wiele opcji w porównaniu z findpoleceniem na SunOS lub Solaris.

Chcę użyć findpolecenia w następujący sposób:

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

Działa idealnie na komputerze z systemem Linux, ale to samo polecenie nie ma opcji -printfna komputerze z systemem SunOS. Chcę dostosować dane wyjściowe w "%TY-%Tm-%Td %f\n"formacie.

Proszę sugerować wszelkie alternatywy dla SunOS.


5
Aby korzystać z GNU findw systemie Solaris, zainstaluj pakiet findutils .
— Kusalananda

Odpowiedzi:


21

Zauważ, że nie ma to nic wspólnego z Linuksem; ten -printfpredykat jest specyficzny dla implementacji GNU find. Linux nie jest systemem operacyjnym, to tylko jądro występujące w wielu systemach operacyjnych. Podczas gdy większość tych systemów operacyjnych korzystała kiedyś z przestrzeni użytkownika GNU, teraz ogromna większość systemów operacyjnych korzystających z Linuksa jest osadzona i ma podstawowe polecenia, jeśli takie mają.

Komenda GNU find, która poprzedza Linuksa, może być zainstalowana na większości systemów operacyjnych uniksopodobnych. Z pewnością był używany w systemie Solaris (wtedy zwanym SunOS), zanim pojawił się Linux.

Obecnie jest nawet dostępny jako pakiet Oracle dla Solaris. W file/gnu-findutilssystemie Solaris 11 jest to włączone , a polecenie ma nazwę gfind(dla GNU find, aby odróżnić je od polecenia systemu find).

Teraz, jeśli nie możesz zainstalować pakietów, najlepszym rozwiązaniem jest prawdopodobnie użycie 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

Nadal używamy find(implementacja Solaris), aby znaleźć pliki, ale używamy jego -execpredykatu, aby przekazać listę plików perl. I perlrobi lstat()na każdym, aby pobrać metadane pliku (w tym czas modyfikacji jako 10. element ( $s[9])), interpretuje go w lokalnej strefie czasowej ( localtime()) i formatuje go ( strftime()), który następnie wyświetla printobok nazwy pliku ( $_jest zmienną pętli, jeśli żaden nie jest podany perli $!jest odpowiednikiem stderror(errno)tekstu błędu dla ostatniego niepowodzenia wywołania systemowego).


Czy nie byłoby miło, gdyby ludzie GNU spojrzeli na istniejące standardy przed wdrożeniem ulepszeń? Istnieje już standard, w jaki sposób używać formatu do określania lsdanych wyjściowych typu, patrz Specyfikacja trybu listy w pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
— schily

5
@schily, GNU find„s -printfwyprzedza POSIX.2, więc ludzie są winni POSIX tutaj. Zauważ też, że specyfikacja POSIX była publiczna dopiero w 2000 roku. Nadal winiłbym ludzi GNU za wprowadzenie ich statponad dekadę później za pomocą innej i gorszej składni dla specyfikacji formatu.
— Stéphane Chazelas,

Czy możesz wspomnieć, kiedy GNU find dodał tę funkcję? Ponieważ system Solaris pax obsługuje ten tryb listy od 1998 r., Myślę, że został wprowadzony z SUSv2.
— schily

1
Możesz także po prostu zainstalować program GNU Find we własnym katalogu bin i ustawić ścieżkę wyszukiwania tego przed katalogami kanonicznymi.
— Peter - Przywróć Monikę

@schily, najwcześniejsza wersja GNU znajduję, że mam 3.1 z 1991 roku, już miała -printf (3.1 dodała dyrektywę formatu% k), dziennik zmian nie wspomina, kiedy został dodany, być może był tam od samego początku. Dziennik zmian pochodzi z 1987 r.
— Stéphane Chazelas,

0

Innym sposobem podejścia jest find2perlskrypt, który konwertuje (tutaj podzbiór) findpolecenia na odpowiedni skrypt perla. Skrypt perla używa File::Findmodułu do ciężkiego podnoszenia. Ponieważ skrypt find2perl w moim systemie nie obsługiwał -printfpredykatu, dodałem go ręcznie:

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

W dwóch przykładowych plikach, które utworzyłem, dane wyjściowe są takie same:

$ 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.