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.


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).


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.