Existem alternativas para o comando `find` no linux para SunOS?

10

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

Eu quero usar o findcomando como este:

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 -printfem uma máquina SunOS. Quero personalizar minha saída no "%TY-%Tm-%Td %f\n"formato.

Por favor, sugira alternativas para o SunOS.

Pratik Mayekar
fonte
5
Para usar o GNU findno Solaris, instale o pacote findutils .
Kusalananda

Respostas:

21

Observe que isso não tem nada a ver com o Linux; esse -printfpredicado é 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 Linux está incorporada e possui comandos básicos, se houver.

O findcomando GNU , que antecede o Linux, pode ser instalado na maioria dos sistemas operacionais do tipo Unix. Certamente foi usado no Solaris (chamado SunOS naquela época) antes do lançamento do Linux.

Atualmente, ele está disponível como um pacote Oracle para Solaris. No Solaris 11, está file/gnu-findutils, e o comando é nomeado gfind(para GNU find, para diferenciá-lo do findcomando 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 Solaris) para encontrar os arquivos, mas estamos usando seu -execpredicado para passar a lista de arquivos perl. E perlexecuta um lstat()em cada um para recuperar os metadados do arquivo (incluindo a hora da modificação como o 10º elemento ( $s[9])), interpreta-o no fuso horário local ( localtime()) e formata-o ( strftime()), que fica printao lado do nome do arquivo ( $_é a variável de loop se nenhum é especificado perle $!é equivalente stderror(errno)ao texto de erro da última falha de chamada do sistema.

Stéphane Chazelas
fonte
Não seria bom se o pessoal do GNU analisasse os padrões existentes antes de implementar melhorias? Já existe um padrão sobre como usar um formato para especificar lssaída de tipo, consulte Especificação de modo Lista no pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
Schily
5
@schily, o GNU findé -printfanterior ao POSIX.2, então o pessoal do POSIX é o culpado aqui. Observe também que a especificação POSIX não era pública até os anos 2000. Eu ainda culparia o pessoal do GNU por apresentar o seu, statmais de uma década depois, com uma sintaxe diferente e inferior para a especificação de formato.
Stéphane Chazelas
Você poderia mencionar quando o GNU find adicionou esse recurso? Como o Solaris pax suporta esse modo de lista desde 1998, acho que foi introduzido no SUSv2.
schily
1
Você também pode simplesmente instalar um gnu find em seu próprio diretório bin e definir o caminho para pesquisar isso antes dos diretórios canônicos.
Peter - Restabelece Monica
@schily, a versão mais antiga do GNU que tenho é 3.1 de 1991, já tinha -printf (3.1 adicionou a diretiva de formato% k), o changelog não menciona quando foi adicionado, possivelmente estava lá desde o início. O ChangeLog remonta a 1987.
Stéphane Chazelas
0

Outra maneira de abordá-lo é com o find2perlscript, que converte (aqui, um subconjunto) de um findcomando em um script perl correspondente. O script perl usa um File::Findmódulo para fazer o trabalho pesado. Como o script find2perl no meu sistema não suportava o -printfpredicado, eu o adicionei 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 que eu criei, 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
Jeff Schaller
fonte