Existe-t-il des alternatives à la commande `find` sur linux pour SunOS?

10

La findcommande sous Linux a beaucoup d'options par rapport à la findcommande sous SunOS ou Solaris.

Je veux utiliser la findcommande comme ceci:

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

Cela fonctionne parfaitement sur une machine Linux, mais la même commande n'a pas l'option -printfsur une machine SunOS. Je souhaite personnaliser ma sortie au "%TY-%Tm-%Td %f\n"format.

Veuillez suggérer des alternatives pour SunOS.

Pratik Mayekar
la source
5
Pour utiliser GNU findsur Solaris, installez le package findutils .
Kusalananda

Réponses:

21

Notez que cela n'a rien à voir avec Linux; ce -printfprédicat est spécifique à l'implémentation GNU de find. Linux n'est pas un OS, c'est juste le noyau trouvé dans un certain nombre d'OS. Alors que la plupart de ces systèmes d'exploitation utilisaient autrefois un espace utilisateur GNU, la grande majorité des systèmes d'exploitation utilisant Linux sont désormais intégrés et ont des commandes de base s'ils en ont.

La findcommande GNU , antérieure à Linux, peut être installée sur la plupart des systèmes d'exploitation de type Unix. Il était certainement utilisé sur Solaris (appelé SunOS à l'époque) avant la sortie de Linux.

De nos jours, il est même disponible en tant que package Oracle pour Solaris. Sous Solaris 11, c'est dans file/gnu-findutilset la commande est nommée gfind(pour GNU find, pour la distinguer de la propre findcommande du système ).

Maintenant, si vous ne pouvez pas installer de packages, votre meilleur pari est probablement d'utiliser 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

Ici, nous utilisons toujours find(implémentation Solaris) pour trouver les fichiers, mais nous utilisons son -execprédicat pour transmettre la liste des fichiers à perl. Et perlfait un lstat()sur chacun pour récupérer les métadonnées du fichier (y compris l'heure de modification en tant que 10ème élément ( $s[9])), l'interprète dans le fuseau horaire local ( localtime()) et le formate ( strftime()) qu'il est ensuite à printcôté du nom de fichier ( $_est la variable de boucle si aucun n'est spécifié dans le texte d'erreur de l'échec du dernier appel système perlet en $!est l'équivalent stderror(errno).

Stéphane Chazelas
la source
Ne serait-il pas agréable que les gens de GNU examinent les normes existantes avant d'implémenter des améliorations? Il existe déjà une norme sur la façon d'utiliser un format pour spécifier le lstype de sortie, voir Spécification du mode liste dans pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
schily
5
@schily, GNU findest -printfantérieur à POSIX.2, donc les gens de POSIX sont à blâmer ici. Notez également que la spécification POSIX n'était pas publique avant les années 2000. Je blâmerais toujours les gens de GNU d'avoir introduit leur statplus d'une décennie plus tard avec une syntaxe différente et inférieure pour sa spécification de format.
Stéphane Chazelas
Pourriez-vous mentionner quand GNU find a ajouté cette fonctionnalité? Étant donné que Solaris pax prend en charge ce mode liste depuis 1998, je suppose qu'il a été introduit avec SUSv2.
schily
1
Vous pouvez également simplement installer une recherche gnu dans votre propre répertoire bin et définir le chemin de recherche avant les répertoires canoniques.
Peter - Rétablir Monica le
@schily, la première version de GNU que j'ai trouvée est 3.1 de 1991, il avait déjà -printf (3.1 a ajouté la directive de format% k), le journal des modifications ne mentionne pas quand il a été ajouté, peut-être qu'il était là depuis le début. Le ChangeLog remonte à 1987.
Stéphane Chazelas
0

Une autre façon de l'aborder est avec le find2perlscript, qui convertit (ici, un sous-ensemble) d'une findcommande en un script perl correspondant. Le script perl utilise un File::Findmodule pour faire le gros du travail. Parce que le script find2perl sur mon système ne supportait pas le -printfprédicat, je l'ai ajouté manuellement:

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

Sur deux exemples de fichiers que j'ai créés, la sortie est la même:

$ 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
la source