Calculando diferença entre duas datas no formato YYYYMMDDHH (Shell)

Neste post vou apresentar um script que escrevi há alguns meses atrás para calcular a diferença entre duas datas quaisquer, no formato YYYYMMDDHH (ou seja, no formato ANO, MÊS, DIA, HORA SINÓTICA).

Exemplo

Qual a diferença (em dias ou em horas) entre as datas “2013010100” e “2013011512”?

O script irá calcular a diferença entre estas duas datas e o resultado será dado em dias e em horas:

$ ./calc_date_diff.ksh 2013010100 2013011512

14 dia(s) e 12 hora(s) ou 348 hora(s)

Script

O script possui o seguinte algorítmo:

  1. Recebe as duas datas pela linha de comando;
  2. As datas são fornecidas como argumentos para a função datediff;
  3. Na função datediff, são separados os anos, os meses, os dias e os horários sinóticos;
  4. A partir disso, são formatadas as datas data1 e data2 no formato ‘YYYY-MM-DD HH:mm:ss UTC’;
  5. Verifica se a data2 é maior ou menor do que data1; se data2 for maior do que data1,
  6. Verifica se HH da data2 é igual a zero e se não é igual a HH da data1;
    1. Se esta verificação for verdadeira, então a diferença entre HH (horas) das datas Informadas será calculada por 24-HH da data1;
    2. Caso contrário, a diferença entre HH (horas) das datas será calculada pela diferença entre os HH da data2 e data1;
  7. Se HH da data1 for igual a zero e HH da data2 não for igual a HH da data1, então a diferença entre HH das datas é calculada por 24 menos HH da data2;
    1. Caso contrário, esta diferença será calculada pela diferença entre HH da data2 e data1.
#! /bin/ksh

#set -o xtrace

data_anl=${1}
data_fct=${2}

datediff(){

  yyyy_anl=$(echo ${data_anl} | cut -c 1-4)
  mm_anl=$(echo ${data_anl} | cut -c 5-6)
  dd_anl=$(echo ${data_anl} | cut -c 7-8)
  hh_anl=$(echo ${data_anl} | cut -c 9-10)

  yyyy_fct=$(echo ${data_fct} | cut -c 1-4)
  mm_fct=$(echo ${data_fct} | cut -c 5-6)
  dd_fct=$(echo ${data_fct} | cut -c 7-8)
  hh_fct=$(echo ${data_fct} | cut -c 9-10)

  data1=$(date -d "${yyyy_anl}-${mm_anl}-${dd_anl} ${hh_anl}:00:00 UTC" "+%s")
  data2=$(date -d "${yyyy_fct}-${mm_fct}-${dd_fct} ${hh_fct}:00:00 UTC" "+%s")

  if [ ${data2} -gt ${data1} ]
  then
    if [ ${hh_fct} -eq "0" -a ${hh_fct} -ne ${hh_anl} ]
    then
      hh_diff=$(( 24-${hh_anl} ))
    else
      hh_diff=$(( ${hh_fct}-${hh_anl} ))
    fi
  else
    if [ ${hh_anl} -eq "0" -a ${hh_fct} -ne ${hh_anl} ]
    then
      hh_diff=$(( 24-${hh_fct} ))
    else
      hh_diff=$(( ${hh_anl}-${hh_fct} ))
    fi
  fi

  dd_diff=$(((${data2}-${data1}) / 86400))

  hh_tot=$((${dd_diff}*24+${hh_diff}))

}

datediff ${data_anl} ${data_fct}

echo "${dd_diff} dia(s) e ${hh_diff} hora(s) ou ${hh_tot} hora(s)"

exit 0

É isso!

Transformando Scripts em Apps no Mac OS X

Scripts em geral são úteis na automatização de tarefas, na organização de processos e tarefas de longa duração. No Mac OS X, existe a possibilidade de se transformar um script em um aplicativo (.app), que pode ser utilizado na inicialização do sistema, logo após o login do usuário. Esta tarefa pode ser realizada utilizando-se o Automator, um programa embutido do Mac OS X que auxilia o usuário a automatizar tarefas, sem a necessidade de se programar um script. Neste post, entretanto, mostrarei como utilizar o Automator para transformar um script em um “App”.

Preparando o Script

Em primeiro lugar, é necessário preparar o script em questão. Se o script recebe argumentos para a sua execução, por exemplo, se ele é executado da seguinte forma:

$ ./script.sh argumento

então, é mais fácil simplificar um pouco o script, se possível, para que seja eliminado o argumento e o script seja executado sem ele. Neste caso, o argumento de entrada – caso seja apenas um tipo único, deve ser “hadrwired” dentro do código. Isso não é interessante em um script, mas para transformá-lo em um “App”, é mais fácil 🙂

Quando o script estiver pronto, sendo possível executá-lo sem a necessidade de argumentos, pode-se abrir o Automator do Mac OS X para preparar o App.

Preparando o App

Abra o Automator (ele fica dentro da pasta Utilities, que fica dentro da pasta Applications). Na tela inicial, selecione “Application”:

Selecionando o tipo Aplicativo no Automator

Selecionando o tipo Aplicativo no Automator

A seguir, selecione a opção “Utilities” (ou Utilitários) e depois a opção “Run Shell Script” (ou Executar Script Shell). Estas opções ficam no painel esquerdo do Automator:

Selecionando a opção a ação "Run Shell Script" no Automator.

Selecionando a opção a ação “Run Shell Script” no Automator.

Depois, clique e arraste a ação “Run Shell Script” (ou Executar Script Shell) para o painel direito do Automator:

Arrastando a ação "Run Shell Script" para o painel direito do Automator.

Arrastando a ação “Run Shell Script” para o painel direito do Automator.

No painel esquerdo do Automator, será aberta uma janela na qual deverá ser digitado o script:

Digite o script na janela posicionada no painel direito do Automator.

Digite o script na janela posicionada no painel direito do Automator.

Depois disso, basta clicar na barra de menus e salvar o “App”:

Salvando o Script em App no Automator.

Salvando o Script em App no Automator.

Depois de salvo, o App se comporta como qualquer outro no Mac OS X, sendo possível – inclusive, adicioná-lo na inicialização do Mac OS X!

Backup local simples com o rsync

O script abaixo tem por objetivo realizar o backup/sincronização (incremental) entre duas pastas diferentes, facilitando e agilizando p processo de cópia de grandes volumes de arquivos.

Algorítmo

O algorítmo deste script segue os seguintes passos:

  1. Verificação dos argumentos de entrada:
    1. Verifica se a quantidade de argumentos não é dois (caso postivo, mostra a função ajuda e finaliza);
    2. Verifica se a quantidade de argumentos é dois (caso positivo, verifica os locais – se são acessíveis ou não);
  2. Com os dois argumentos de entrada (origem e destino, respectivamente), chama a função backup
  3. Finaliza o script
#!/bin/ksh
#set -o xtrace
ajuda() {
print "Uso: ./backup_rsync.ksh <origem> <destino>"
 exit 1
}
backup() {
origem=${1}
 destino=${2}
rsync -av ${origem}/ ${destino}/
}
if [ $# -ne 2 ]
 then
ajuda
elif [ $# -eq 2 ]
 then
print "Verificando os locais:"
 print "${1}"
 print "${2}"
if [ ${1} == ${2} ]
 then
print "${1} e o mesmo local de destino (${2})"
 exit 1
elif [ ${1} != ${2} -a -r ${1} -a -w ${2} ]
 then
backup ${1} ${2}
else
print "${1} inacessivel ou ${2} nao pode ser escrito"
 exit 1
fi
else
ajuda
fi
exit 0

Exemplo

No exemplo abaixo, serão sincronizadas as pastas “teste1” e “teste2”, ambas presentes no mesmo diretório em que o script será executado (o que não é uma necessidade). Cada uma das pastas contém os arquivos “arquivo1” e “arquivo2”, respectivamente. O objetivo é fazer com que a “pasta2” contenha os “arquivo1” e “arquivo2”. Em qualquer caso, nenhum arquivos é apagado.

./backup_rsync.ksh teste2 teste1
 Verificando os locais:
 teste2
 teste1
 sending incremental file list
 arquivo2
sent 127 bytes received 31 bytes 316.00 bytes/sec
 total size is 0 speedup is 0.00

Observações

  • Na primeira vez em que o script for utilizado, pode ser que leve um tempo maior; depois disso, o processo de sincronização é mais rápido;
  • Na linha 17 do script, a barra no final de ${origem} e ${destino} é necessária para que o conteúdo de ${origem} seja armazenado no primeiro nível de ${destino}, caso contrário a pasta ${origem} será criada dentro de ${destino}.