Existem alternativas ao comando 'find' no linux para o SunOS?

10

O comando find no Linux tem muitas opções em comparação com o comando find no SunOS ou no Solaris.

Eu quero usar o comando find da seguinte forma:

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

Funciona perfeitamente em uma máquina Linux, mas o mesmo comando não tem a opção -printf em uma máquina SunOS. Desejo personalizar minha saída no formato "%TY-%Tm-%Td %f\n" .

Por favor, sugira quaisquer alternativas para o SunOS.

    
por Pratik Mayekar 18.06.2018 / 08:04

2 respostas

21

Note que não tem nada a ver com o Linux; esse predicado -printf é específico para a implementação GNU de find . O Linux não é um sistema operacional, é apenas o kernel encontrado em vários sistemas operacionais. Enquanto a maioria desses sistemas operacionais costumava usar uma área de usuário GNU no passado, agora a grande maioria dos sistemas operacionais que usam o Linux estão incorporados e possuem comandos básicos, se tiverem algum.

O comando GNU find , que antecede o Linux, pode ser instalado na maioria dos sistemas operacionais baseados em Unix. Foi certamente usado no Solaris (chamado SunOS naquela época) antes do lançamento do Linux.

Atualmente, ele está disponível como um pacote do Oracle para Solaris. No Solaris 11, isso é em file/gnu-findutils , e o comando é chamado de gfind (para o GNU find , para diferenciá-lo do comando find do próprio sistema).

Agora, se você não pode instalar pacotes, sua melhor aposta é provavelmente usar 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

Aqui, ainda estamos usando find (implementação do Solaris) para encontrar os arquivos, mas estamos usando o predicado -exec para passar a lista de arquivos para perl . E perl faz um lstat() em cada para recuperar os metadados do arquivo (incluindo o tempo de modificação como o 10º elemento ( $s[9] )), interpreta no fuso horário local ( localtime() ) e formata ( strftime() ) que então print s ao lado do nome do arquivo ( $_ é a variável de loop se nenhum for especificado em perl e $! for o equivalente a stderror(errno) , o texto do erro da última falha de chamada do sistema ).

    
por 18.06.2018 / 08:24
0

Outra maneira de abordá-lo é com o script find2perl , que converte (aqui, um subconjunto) de um comando find em um script perl correspondente. O script perl usa o módulo File::Find para fazer o trabalho pesado. Como o script find2perl no meu sistema não suportava o predicado -printf , adicionei-o 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;

Em dois arquivos de amostra criados, a saída é a mesma:

$ 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
    
por 21.06.2018 / 22:20