Gibt es Alternativen zum Befehl `find` unter Linux für SunOS?

10

Der findBefehl unter Linux bietet im Vergleich zum findBefehl unter SunOS oder Solaris viele Optionen .

Ich möchte den findBefehl wie folgt verwenden:

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

Es funktioniert einwandfrei auf einem Linux-Computer, aber der gleiche Befehl hat -printfauf einem SunOS-Computer nicht die Option . Ich möchte meine Ausgabe im "%TY-%Tm-%Td %f\n"Format anpassen .

Bitte schlagen Sie Alternativen für SunOS vor.

Pratik Mayekar
quelle
5
findInstallieren Sie das findutils- Paket , um GNU unter Solaris zu verwenden .
Kusalananda

Antworten:

21

Beachten Sie, dass es nichts mit Linux zu tun hat. Dieses -printfPrädikat ist spezifisch für die GNU-Implementierung von find. Linux ist kein Betriebssystem, sondern nur der Kernel einer Reihe von Betriebssystemen. Während die meisten dieser Betriebssysteme in der Vergangenheit ein GNU-Benutzerland verwendeten, ist jetzt die große Mehrheit der Betriebssysteme, die Linux verwenden, eingebettet und verfügen über grundlegende Befehle, falls vorhanden.

Der GNU- findBefehl vor Linux kann auf den meisten Unix-ähnlichen Betriebssystemen installiert werden. Es wurde sicherlich unter Solaris (damals SunOS genannt) verwendet, bevor Linux herauskam.

Heutzutage ist es sogar als Oracle-Paket für Solaris verfügbar. Unter Solaris 11 ist dies der Fall file/gnu-findutils, und der Befehl wird benannt gfind(für GNU find, um ihn vom systemeigenen findBefehl zu unterscheiden).

Wenn Sie keine Pakete installieren können, verwenden Sie wahrscheinlich am besten Folgendes 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

Hier verwenden wir immer noch find(Solaris-Implementierung), um die Dateien zu finden, aber wir verwenden das -execPrädikat, um die Liste der Dateien an zu übergeben perl. Und perlführt lstat()jeweils ein a aus, um die Dateimetadaten abzurufen (einschließlich der Änderungszeit als 10. Element ( $s[9])), interpretiert sie in der lokalen Zeitzone ( localtime()) und formatiert sie ( strftime()), die dann printneben dem Dateinamen steht ( $_ist die Schleifenvariable, wenn Keine ist im Fehlertext für den letzten Systemaufruffehler angegeben perlund $!entspricht diesem stderror(errno).

Stéphane Chazelas
quelle
Wäre es nicht schön, wenn die GNU-Mitarbeiter sich vor der Implementierung von Verbesserungen mit bestehenden Standards befassen würden? Es gibt bereits einen Standard für die Verwendung eines Formats zur Angabe der Typausgabels , siehe Spezifikation des Listenmodus
schily
5
@schily, GNU find‚s -printffrüher POSIX.2, so sind die POSIX Leute hier schuld. Beachten Sie auch, dass die POSIX-Spezifikation erst in den 2000er Jahren öffentlich war. Ich würde den GNU-Leuten immer noch die Schuld geben, dass sie ihre statüber ein Jahrzehnt später mit einer anderen und minderwertigen Syntax für ihre Formatspezifikation eingeführt haben.
Stéphane Chazelas
Könnten Sie erwähnen, wann GNU find diese Funktion hinzugefügt hat? Da Solaris pax diesen Listenmodus seit 1998 unterstützt, wurde er vermutlich mit SUSv2 eingeführt.
schily
1
Sie können auch einfach einen gnu find in Ihrem eigenen bin-Verzeichnis installieren und den Pfad für die Suche vor den kanonischen Verzeichnissen festlegen.
Peter - Reinstate Monica
@schily, die früheste Version von GNU find, die ich habe, ist 3.1 von 1991, sie hatte bereits -printf (3.1 hat die Direktive% k format hinzugefügt), das Änderungsprotokoll erwähnt nicht, wann es hinzugefügt wurde, möglicherweise war es von Anfang an da. Das ChangeLog geht auf das Jahr 1987 zurück.
Stéphane Chazelas
0

Eine andere Möglichkeit ist das find2perlSkript, das (hier eine Teilmenge) eines findBefehls in ein entsprechendes Perl-Skript konvertiert . Das Perl-Skript verwendet ein File::FindModul, um das schwere Heben durchzuführen. Da das Skript find2perl auf meinem System das -printfPrädikat nicht unterstützte , habe ich es manuell hinzugefügt:

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

Bei zwei von mir erstellten Beispieldateien ist die Ausgabe dieselbe:

$ 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
quelle