Ci sono alternative al comando `find` su linux per SunOS?


10

Il findcomando su Linux ha molte opzioni rispetto al findcomando su SunOS o Solaris.

Voglio usare il findcomando in questo modo:

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

Funziona perfettamente su una macchina Linux, ma lo stesso comando non ha l'opzione -printfsu una macchina SunOS. Voglio personalizzare il mio output nel "%TY-%Tm-%Td %f\n"formato.

Si prega di suggerire eventuali alternative per SunOS.


5
Per usare GNU findsu Solaris, installare il pacchetto findutils .
Kusalananda

Risposte:


21

Nota che non ha nulla a che fare con Linux; quel -printfpredicato è specifico per l'implementazione GNU di find. Linux non è un sistema operativo, è solo il kernel presente in diversi sistemi operativi. Mentre la maggior parte di quei sistemi operativi utilizzava in passato un'area utente GNU in passato, ora la maggior parte dei sistemi operativi che utilizzano Linux sono incorporati e dispongono di comandi di base, se presenti.

Il findcomando GNU , che precede Linux, può essere installato sulla maggior parte dei sistemi operativi simili a Unix. Fu certamente usato su Solaris (chiamato SunOS allora) prima che Linux uscisse.

Oggi è persino disponibile come pacchetto Oracle per Solaris. Su Solaris 11, c'è file/gnu-findutils, e il comando è chiamato gfind(per GNU find, per distinguerlo dal findcomando stesso del sistema ).

Ora, se non riesci a installare i pacchetti, la soluzione migliore è probabilmente usare 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

Qui, stiamo ancora usando find(implementazione Solaris) per trovare i file, ma stiamo usando il suo -execpredicato per passare l'elenco dei file perl. E perlfa uno lstat()su ciascuno per recuperare i metadati del file (incluso il tempo di modifica come il 10 ° elemento ( $s[9])), lo interpreta nel fuso orario locale ( localtime()) e lo formatta ( strftime()) che poi printaffianca il nome del file ( $_è la variabile del ciclo se nessuna è specificata nel testo dell'errore per l'ultimo errore di chiamata di sistema perled $!è l'equivalente di stderror(errno)).


Non sarebbe bello se le persone GNU avessero esaminato gli standard esistenti prima di implementare i miglioramenti? Esiste già uno standard su come utilizzare un formato per specificare lsuscita tipo, vedi Elenco specifiche modalità in pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
Schily

5
@schily, GNU finds' -printfessere anteriore POSIX.2, così la gente POSIX sono da biasimare qui. Si noti inoltre che le specifiche POSIX non erano pubbliche fino agli anni 2000. Darei ancora la colpa alla gente di GNU per aver introdotto la loro statoltre un decennio dopo con una sintassi diversa e inferiore per le sue specifiche di formato.
Stéphane Chazelas,

Potresti dire quando GNU ha trovato quella funzione? Poiché Solaris pax supporta questa modalità elenco dal 1998, immagino sia stata introdotta con SUSv2.
schily,

1
Potresti anche semplicemente installare un gnu find nella tua directory bin e impostare il percorso per cercarlo prima delle directory canoniche.
Peter - Ripristina Monica il

@schily, la prima versione di GNU che ho trovato è la 3.1 del 1991, aveva già -printf (3.1 ha aggiunto la direttiva sul formato% k), il log delle modifiche non menziona quando è stato aggiunto, forse era lì dall'inizio. Il ChangeLog risale al 1987.
Stéphane Chazelas,

0

Un altro modo per affrontarlo è con lo find2perlscript, che converte (qui, un sottoinsieme) di un findcomando in uno script perl corrispondente. Lo script perl utilizza un File::Findmodulo per eseguire il sollevamento di carichi pesanti. Poiché lo script find2perl sul mio sistema non supportava il -printfpredicato, l'ho aggiunto manualmente:

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

Su due file di esempio che ho creato, l'output è lo stesso:

$ 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.