Verificando a Data de Modificação de um Arquivo no Bash

O comando stat exibe informações de um arquivo ou de um diretório. Esse comando é bem mais útil do que o comando ls para esse propósito. O comando date exibe a data atual do sistema operacional e também pode ser utilizado para formatar uma data de acordo com um determinado padrão. Nesse artigo, veremos como utilizar esses dois comandos para verificar a data de atualização de um arquivo.

   # Obtem a data de modificação do arquivo em formato 
   # legível (2018-05-01 01:00:00.976116935 +1100)
   FILE=$(stat -c %y "arquivo.txt" );

   # Obtem o trecho da string de data referente ao ano, mês e dia
   FILE=${FILE:0:10};

   # Obtem a data de atualização do arquivo em segundos
   FILE=$(date --date=$FILE +%s);

   DATA="2018-05-01";

   # Obtem a data informada em segundos
   DATA=$(date --date=$DATA +%s);
   
   if [ $(($DATA-$FILE)) -lt 0 ]; then 
      # Faz alguma coisa...
   fi

Se seus script foi escrito no Windows, ele apresentará caracteres não reconhecíveis pelo bash. Você deve executar o comando abaixo para limpar o arquivo:

sed -i -e 's/\r$//' seu_script.sh

Referências

1. [https://stackoverflow.com/questions/1207052/how-to-use-shell-script-checking-last-changed-time-of-a-file]
2. [https://www.linuxquestions.org/questions/programming-9/get-file-modification-date-time-in-bash-script-163731/]
3. [https://unix.stackexchange.com/questions/187966/calculate-date-difference-between-last-modified-date-of-a-file-and-now-using-she]
4. [http://chriscase.cc/2013/05/getting-the-creation-timestamp-of-a-file-with-stat/]

Anúncios
Categorias:Programação

Epistemologia da Integração de Funções Compostas

Em outro artigo, demonstrei como se chega na fórmula das derivadas compostas utilizando logaritmo:

f'(x) = u'(x).v(x) + v'(x).u(x)

Podemos generalizar essa fórmula assim:

[uv]’ = u’v + uv’

Nesse artigo, vou apresentar a epistemologia da integração por partes. Vou utilizar a versão genérica, mas você pode fazer um intervalo definido de a até b:

[uv]’ = u’v + uv’

[uv]’ = u’v + uv’

uv = u’v + uv’

u’v = uv – uv’

Vamos demonstrar com um exemplo:

ln x dx

1 . ln x dx

Trabalhando as variáveis da integração por partes:

u = x ∴ u’ = 1
v = ln x ∴ v’ = 1/x

Substituindo na integral:

lnx dx = xlnx – x1/xdx
lnx dx = xlnx – dx

E simplificando:

lnx dx = xlnx – x + c
Categorias:Matemática Tags:

Views Materializadas

Uma view é uma consulta que retorna um conjunto de dados de uma ou mais tabelas e pode ser acessada por nome. A view sempre representa o estado atual do dado acessado, pois sempre que é acionada ela regera seu conjunto de dados.

CREATE VIEW VW_PESSOA (CPF, NOME)
AS 
SELECT PESSOA.CPF,PESSOA.NOME
FROM  TBL_PESSOA PESSOA;

Uma view materializada tem o mesmo objetivo da view, mas quando ela é criada o resultado de sua consulta é armazenado em banco em uma estrutura tabular.

CREATE MATERIALIZED VIEW MVW_PESSOA (CPF, NOME)
AS 
SELECT PESSOA.CPF,PESSOA.NOME
FROM  TBL_PESSOA PESSOA;

A vantagem dessa abordagem é que o dado acessado sempre estará disponível, pois a consulta não será reexecutada quando a view materializada for chamada. Devido ao seu caráter estático, é necessário estabelecer um processo para atualizá-la. Pode-se, por exemplo, utilizar uma trigger ou configurar a crontab.

Tanto a view quanto a view materializada, devido ao comportamento tabular que apresentam, podem ser mapeadas como tabelas na sua aplicação:

@Table(name = "MVW_PESSOA")
public class PessoaView{
   @Id
   @Column(name = "CPF")
   private Long cpf;

   @Column(name = "NOME")
   private String nome;
}

Alternativas para Conversão de PDF em Imagens

Há alguns anos, me deparei com o problema de converter PDFs para imagens em uma aplicação. Fiz estudos com algumas bibliotecas Java, mas não gostei muito do resultado. As bibliotecas gratuitas em geral produziam imagens com qualidade baixa e às vezes sequer convertiam o arquivo PDF em função de algum recurso inerente ao arquivo e que era desconhecido para a ferramenta. Mesmo assim, os maiores problemas que encontrei eram referentes à performance e ao uso de memória, pois a conversão era feita pela aplicação Java. Inicialmente pensei em uma máquina dedica para a conversão dos arquivos, mas deixei essa ideia em stand by enquanto pesquisava alguma alternativa, pois às vezes o aumento de recursos físicos ataca o efeito colateral de problemas produzidos por nossa própria implementação.

Um colega indicou o Ghostscript, que é escrito em C e roda como um processo no sistema operacional. Fizemos uma implementação multithread em Java que gravava o arquivo PDF em disco, delegava ao Ghostscript – e para o sistema operacional – a tarefa de converter o arquivo para imagem e depois coletava os resultados. Depois de alguns tunnings, as imagens ficaram com qualidade próxima à original.

Nesse artigo, vou compartilhar os códigos de exemplo que produzi para entender como funcionavam algumas das bibliotecas de conversão de arquivos que estudei antes e depois da implementação do Ghostscript.

PDFBox

O PDFBox da Apache foi a primeira biblioteca que testei. Ele já era bem conhecido e maduro.

<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
   <version>1.7.1</version>
</dependency>
		
<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-log4j12</artifactId>
   <version>1.7.1</version>
</dependency>
		
<dependency>
   <groupId>org.apache.pdfbox</groupId>
   <artifactId>pdfbox</artifactId>
   <version>1.8.3<
</dependency>

A implementação ficou assim:

public class PDFBoxPdfToImage {
   public static void main(String[] args) throws Exception{
      String sourceDir = "C:/tmp/teste.pdf";
      String destinationDir = "C:/tmp/";
      File sourceFile = new File(sourceDir);
      PDDocument document = PDDocument.load(sourceDir);
      @SuppressWarnings("unchecked")
      List<PDPage> list = document.getDocumentCatalog().getAllPages();
      sourceFile.getName().replace(".pdf", "");
      int pageNumber = 1;
      for (PDPage page : list) {
         BufferedImage image = page.convertToImage(BufferedImage.TYPE_INT_RGB, 100);
         File outputfile = new File(destinationDir + pageNumber + ".jpeg");
         ImageIO.write(image, "png", outputfile);
         pageNumber++;
      }
      document.close();
   }
}

Nesse exemplo, converti um arquivo PDF qualquer, página à página, com resolução de 100dpi. Para arquivos PDF simples, a qualidade final da imagem até que ficou razoável, mas muitos PDFs mais complexos, cheios de figuras e camadas, sequer foram convertidos: a biblioteca gerou páginas pretas.

jPDFImages

O jPDFImages é uma biblioteca paga da Qoppa Software. Você pode baixar o jar trial deles.

import java.io.File;
import com.qoppa.pdfImages.PDFImages;

public class PDFToImage {
   public static void main(String[] args) throws Exception {
      String sourceDir = "C:/tmp/teste.pdf";
      String destinationDir = "C:/tmp/";
      File base = new File(destinationDir + "/");
      if (!base.exists()) {
         base.mkdir();
      }
      PDFImages pdfDoc = new PDFImages(sourceDir, null);
      for (int count = 0; count < pdfDoc.getPageCount(); ++count) {
         pdfDoc.savePageAsJPEG(count, destinationDir + "/" + count + ".jpg", 100, 0.9f);
      }
   }
}

Nesse exemplo, converti um arquivo PDF qualquer, página à página, com resolução de 100dpi e 90% de qualidade. Qualquer arquivo que tentei converter, até os mais complexos, ficaram com qualidade excelente.

Ghost4J

O Ghost4J fornece uma API que abstrai o uso do Ghostscript. O Ghostscript deve estar instalado e rodando para que o Ghost4J funcione.

<dependency>
   <groupId>org.ghost4j</groupId>
   <artifactId>ghost4j</artifactId>
   <version>1.0.0</version>
</dependency>

No primeiro exemplo abaixo, configuro o Ghost4J para utilizar explicitamente as configurações do Ghostscript para conversão e gravar as imagens no diretório C:/tmp.

import java.awt.image.RenderedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.ghost4j.Ghostscript;
import org.ghost4j.GhostscriptException;

public class Ghost4jPDFToImage {
   public static void main(String[] args) throws Exception {
       Ghostscript gs = Ghostscript.getInstance();
       synchronized (gs) {
          List<String> gsArgs = new ArrayList<String>();
          gsArgs.add("gswin64c");
          gsArgs.add("-dNOPAUSE");
          gsArgs.add("-dBATCH");
          gsArgs.add("-dSAFER");
          gsArgs.add("-dGraphicsAlphaBits=4");
          gsArgs.add("-dTextAlphaBits=4");
          gsArgs.add("-dDOINTERPOLATE");
          gsArgs.add("-sDEVICE=display");
          gsArgs.add("-sDisplayHandle=0");
          gsArgs.add("-dDisplayFormat=16#804");
          gsArgs.add("-r100");
          gsArgs.add("-sOutputFile=C:/tmp/%0000d.jpeg");
          gsArgs.add("C:/tmp/teste.pdf");
          gs.initialize(gsArgs.toArray(new String[gsArgs.size()]));
          gs.exit();
      }
      try {
         Ghostscript.deleteInstance();
      } catch (GhostscriptException e) {
         System.out.println("ERROR: " + e.getMessage());
      }
   }
}

Esse segundo exemplo também utiliza explicitamente as configurações do Ghostscript, mas adicionei também um um ImageWriterDisplayCallback para delegar para a aplicação o controle dos arquivos de imagem gerados.

import java.awt.image.RenderedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.ghost4j.Ghostscript;
import org.ghost4j.GhostscriptException;
import org.ghost4j.display.ImageWriterDisplayCallback;

public class Ghost4jPDFToImage {
   public static void main(String[] args) throws Exception {
      Ghostscript gs = Ghostscript.getInstance();
      ImageWriterDisplayCallback displayCallback = new ImageWriterDisplayCallback();
      gs.setDisplayCallback(displayCallback);
      synchronized (gs) {
         List<String> gsArgs = new ArrayList<String>();
         gsArgs.add("gswin64c");
         gsArgs.add("-dNOPAUSE");
         gsArgs.add("-dBATCH");
         gsArgs.add("-dSAFER");
         gsArgs.add("-dGraphicsAlphaBits=4");
         gsArgs.add("-dTextAlphaBits=4");
         gsArgs.add("-dDOINTERPOLATE");
         gsArgs.add("-sDEVICE=display");
         gsArgs.add("-sDisplayHandle=0");
         gsArgs.add("-dDisplayFormat=16#804");
         gsArgs.add("-r100");
         gsArgs.add("-sOutputFile=C:/tmp/%0000d.jpeg");
         gsArgs.add("C:/tmp/teste.pdf");
         gs.initialize(gsArgs.toArray(new String[gsArgs.size()]));
         gs.exit();
      }
      for (int i = 0; i < displayCallback.getImages().size(); i++) {
         ImageIO.write((RenderedImage) displayCallback.getImages().get(i), "jpeg",
               new File("C:/tmp/" + i + ".jpeg"));
      }
      try {
         Ghostscript.deleteInstance();
      } catch (GhostscriptException e) {
         System.out.println("ERROR: " + e.getMessage());
      }
   }
}

Essa última implementação é mais simples e utiliza, implicitamente, o Ghostscript instalado na máquina:

import java.awt.Image;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.ghost4j.Ghostscript;
import org.ghost4j.GhostscriptException;
import org.ghost4j.document.PDFDocument;
import org.ghost4j.renderer.SimpleRenderer;

public class Ghost4jPDFToImage {
   public static void main(String[] args) throws Exception{
      PDFDocument document = new PDFDocument();
      document.load(new File("C:/tmp/teste.pdf"));
      SimpleRenderer renderer = new SimpleRenderer();
      renderer.setResolution(100);
      renderer.setAntialiasing(SimpleRenderer.OPTION_ANTIALIASING_HIGH );
      List<Image> images = renderer.render(document);
      try {
         for (int i = 0; i < images.size(); i++) {
            ImageIO.write((RenderedImage) images.get(i), "png", new File("C:/tmp/" + (i + 1) + ".png"));
	 }
      } catch (IOException e) {
         System.out.println("ERROR: " + e.getMessage());
      }
   }
}

Você poderia modificar essa implementação para utilizar várias Threads para conversão de imagens conforme a documentação oficial.

Categorias:Programação

Encontrando o X na Potenciação Através de um Artifício

O Canal Mind Your Decisions mostrou um artifício bem legal para resolver um determinado problema de potenciação. O problema era encontrar o valor de X na equação abaixo:

(3+4)(32+42)(34+44)(38+48)(316+416)(332+432) = (4x-3x)

Para começar, como quem não quer nada, ele apenas modificou a ordem dos termos dentro dos parenteses do lado esquerdo da equação:

(41+31)(42+32)(44+34)(48+38)(416+316)(432+332) = (4x-3x)

Por que ele fez isso? Ele estipulou como objetivo reduzir a equação utilizando o quadrado da diferença:

(a2-b2) = (a+b)(a-b)

Porém, estava faltando o termo inicial para juntar com (41+31). É aí que vem a sacada do autor do vídeo. Muda alguma coisa se você multiplicar os dois lados por “1”? Não, né?

1(41+31)(42+32)(44+34)(48+38)(416+316)(432+332) = (4x-3x)1

O “1” pode ser escrito de várias formas diferentes:

5/5 = 1
33 * 2 – 65 = 1

Mas estamos interessados em um formato que nos ajude a montar o quadrado da diferença. Esse aqui:

(4-3) = 1

O que permite escrever:

(41-31)(41+31)(42+32)(44+34)(48+38)(416+316)(432+332) = (4x+3x)(41-31)

(42-32)(42+32)(44+34)(48+38)(416+316)(432+332) = (4x-3x)1

(44-34)(44+34)(48+38)(416+316)(432+332) = (4x-3x)

(48-38)(48+38)(416+316)(432+332) = (4x-3x)

(416-316)(416+316)(432+332) = (4x-3x)

(432-332)(432+332) = (4x-3x)

(464-364) = (4x-3x)

X = 64

Categorias:Matemática Tags:

Conversão de Milhas para Quilômetros Utilizando Fibonacci

Você sabia que é possível fazer uma conversão rápida de milhas para quilômetros com uma margem de erro bem baixa (≅1%)? Basta conhecer o número de ouro e sua relação com a sequência de Fibonacci:

Fibonacci (F): 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, …

Número de ouro (Fn+1/Fn): 1/0, 1/1, 2/1, 3/2, 5/3, …, 1,6180339…

1 milha vale 1,609340 quilômetros. O número de ouro, que é a relação entre dois números consecutivos da sequência de Fibonacci quando esta tende ao infinito, é 1,6180339. Para realizar a a conversão, você deve aproximar o valor que você converter de Fn e observar o valor que o sucede – Fn+1 é o valor “convertido” que você procura.

Como exemplo, lembra da velocidade a que chegava o DeLorean para que o Capacitor de Fluxos ativasse os circuitos do tempo? Eram 88 milhas por hora. Na sequência de Fibonacci, o números mais próximo daquele é 89 e o número que vem a seguir é o 144. Então, uma aproximação razoável de 88 milhas para o equivalente em quilômetros é 144.

Uma curiosidade sobre as 88 milhas por hora do filme De Volta para o Futuro: sabe por que essa velocidade foi escolhida? Por que os designers de produção acreditavam que era um número condizente com velocímetros digitais e seria fácil de memorizar. Isso é para evitar teorias inúteis, como aquelas sobre o número 42 do Guia do Mochileiro das Galáxias.

As Reflexões de Douglas Adams

No dia 25 de maio foi comemorado o Dia da Toalha, que foi criado por fãs para homenagear Douglas Adams (1952-2001), autor de O Guia do Mochileiro das Galáxias. O blog Geekness publicou as 42 reflexões sobre a vida, o universo e tudo mais.

Figura 1 – Douglas Adams

1. “A experiência de aprendizagem é uma daquelas coisas que diz, “Sabe aquilo que você acabou de fazer? Não faça.”

2. “Eu posso não ter ido onde gostaria, mas acho que cheguei onde deveria.”

3. “Vamos pensar o impensável, vamos fazer o impossível. Vamos nos preparar para lidar com o próprio inefável, e ver se não podemos expressá-lo depois.”

4. “A qualidade de qualquer conselho que alguém pode dar deve ser julgado referente à qualidade de vida que a mesma leva.”

5. “Eu me recuso em responder essa pergunta baseado na premissa de não saber a resposta.”

6. “É um erro acreditar que é possível resolver qualquer problema importante usando batatas.”

7. “As opiniões não são iguais. Algumas são muito mais robustas, sofisticadas e bem apoiada na lógica e argumento de que outras.”

8. “Eu amo prazos. Adoro prazos. Adoro o barulho de vento que eles fazem quando os dias vão passando.”

9. “A ideia era fantasticamente, descontroladamente improvável. Mas como a maioria das ideias fantasticamente, descontroladamente improváveis, era pelo menos tão digna de consideração quanto uma mais mundana em que os fatos tenham sido vigorosamente dobrados para se encaixarem.”

10. “Eu prefiro ser feliz do que estar certo.”

11. “Apenas uma criança vê as coisas com perfeita clareza, porque não desenvolveu todos os filtros que nos impedem de ver as coisas que nós não esperamos ver.”

12. “Realidade é frequentemente imprecisa.”

13. “O que eu preciso agora… é uma bebida forte e meus amigos.”

14. “É tolice dizer que você sabe o que está acontecendo com outras pessoas. Só eles sabem, se eles existirem. Eles têm os seus próprios universos de seus próprios olhos e ouvidos.”

15. “Não há razão alguma em usar a palavra “impossível” para descrever algo que claramente aconteceu.”

16. “Uma pessoa nunca está sozinha com um pato de borracha.”

17. “Beethoven diz como é ser Beethoven e Mozart diz como é ser humano. Bach diz como é ser o universo.”

18. “Qualquer coisa que pensa logicamente pode ser enganada por outra coisa que pensa e faz logicamente da mesma forma.”

19. “Deixe o passado se prender e o presente avançar para o futuro.”

20. “Não aceito a atual afirmação que está na moda de que, qualquer ponto de vista é automaticamente digno de respeito como qualquer outro ponto de vista igualmente oposto.”

21. “O tempo é uma ilusão. A hora do almoço é uma ilusão maior ainda.”

22. “O impossível muitas vezes tem um tipo de integridade que falta no meramente improvável.”

23. “A vida é desperdiçada ao ser vivida.”

24. “Há algumas pessoas que você gosta de imediato, algumas que você acha que pode aprender a gostar na plenitude do tempo, e algumas que você simplesmente quer empurrar para longe com uma vara afiada.”

25. “Eu levaria o temor de entendimento sobre o temor da ignorância em qualquer dia.”

26. “Tudo o que você realmente precisa saber no momento é que o universo é muito mais complicado do que se poderia pensar, mesmo se você começar a partir de uma posição já pensando que ele é muito complicado.”

27. “Qualquer coisa inventada depois dos seus 35 anos é contra a ordem natural das coisas.”

28. “Uma vida sobrecarregado com expectativas é uma vida pesada. Seu fruto é tristeza e decepção.”

29. “Se você tentar abrir um gato para ver como ele funciona, a primeira coisa que você vai ter em suas mãos é um gato que não funciona.”

30. “Pessoas que precisam te intimidar são as mais fáceis de controlar.”

31. “Temos normalidade. Repito, temos normalidade. Qualquer coisa que você ainda não pode lidar é, portanto, problema seu.”

32. “A beleza não precisa ter alguma explicação. O que é um vaso? O que é um pôr do sol ou uma flor? Sobre o que é, aliás, é Vigésima Terceira Concerto para Piano de Mozart?”

33. “Qualquer pessoa capaz de se tornar Presidente não deveria ser permitida de fazer esse trabalho.”

34. “Mesmo um robô maníaco-depressivo é melhor para conversar do que ninguém.”

35. “Meu universo é meus olhos e meus ouvidos. Todo o resto é boato.”

36. “Se isso se parece com um pato, e grasna como um pato, temos que, pelo menos, considerar a possibilidade de que temos um pequeno pássaro aquático da família anatidae em nossas mãos.”

37. “Uma xícara de chá restauraria minha normalidade.”

38. “Os seres humanos, que são quase a única espécie que tem a capacidade de aprender com a experiência dos outros, também são notáveis por sua aversão aparente para fazê-lo.”

39. “Pode ser muito perigoso ver as coisas do ponto de vista de outra pessoa sem o devido treinamento.”

40. “Você vive e aprende. De qualquer forma, você vive.”

41. “Não acredite em tudo que lê na internet. Exceto isso. Bem, incluindo isso, eu acho.”

42. “Não entre em pânico.”