sábado, 22 de setembro de 2012

Da base decimal para as bases binária, hexadecimal e octal

Há muito tempo já tinha reparado que não existia uma função pronta que converte da base decimal para binária.

Eu estava enganado e um professor falou da função itoa. No entanto, para minha decepção, a função não funciona apresentando o erro abaixo:

teste.c:(.text+0x4f): undefined reference to `itoa'

Como disse um velho amigo de programação: "você não precisa saber todos os comandos, funções e etecera. Se for criativo, você contorna a situação". Então criei minha própria forma de converter de decimal para binário. Basta executar o programa na linha de comando passando como parâmetro o número na base decimal. O código em C++ contém comentários descrevendo suas etapas.

Bibliotecas necessárias:

  • iostream
  • iomanip
  • cstdlib

Para converter de decimal para binário, a primeira tarefa é determinar a quantidade de divisões. Para tal, foi preciso que primeiro cálculo fosse feito fora do while para determinar o valor do quociente. Só então o loop while começa incrementando a variável divisoes.

A cada divisão, o valor do resto é armazenado em um vetor. Assim, cada cálculo, um índice é preenchido.

Para exibir o resultado, é impresso o quociente encontrado na última divisão e o vetor de restos do maior para o menor índice.

Para o valor hexadecimal, a namespace hex converte para hexadecimal. Finalmente, para o valor octal, a namespace oct converte para octal.

Apresento o código-fonte abaixo.


// Created by Murilo Fujita <murilofujita@gmail.com> in 09/21/2012

#include <iostream>
using std::cin;
using std::cout;
using std::endl;
#include <iomanip>
using std::setprecision;
using std::setw;
#include <cstdlib>
using std::hex;
using std::oct;

int main(int argc, char** argv) {

    int pos=50; //quantidade de POSICOES do array
    int num,quo,res[pos], divisoes, numero;

    if (argc <2)
    {
      cout << "Digite um número na base decimal" << endl;
      exit(1);
    }

    num=atoi(argv[1]);

    numero=num; // num é usado para calculos; numero é usado para recuperar o input
    divisoes=0; // inicializa a quantidade de divisoes

    quo=num/2;
    res[0]=num%2; // precisa calcular o primeiro resto para o WHILE saber como comeca

    pos=1; // comeca em 1 porque o indice 0 ja foi calculado fora do loop
    while (quo>1)
    {
        quo=num/2; // quociente
        res[pos++]=num%2; // armezena os restos
        num=quo; // sacada para realizar as divisoes sucessivas
        divisoes++; //conta a quantidade de divisoes
    }
    cout << numero << " precisa de " << divisoes+1 << " bits." << endl;

    pos=divisoes;
    cout << "binário: ";
    cout << quo; // imprime o bit mais significativo: o quociente da ultima divisao
    for (int j=divisoes; j>0; j--)
    {
       cout << res[pos--]; // imprime os restos do ultimo indice para o primeiro
    }

    cout << endl;
    cout << "hexadecimal: " << hex << numero << endl;
    cout << "octal: " <<  oct << numero << endl;
    return 0;
}

E para concluir, dois exemplos da resposta do programa:

./bases_numericas.out 51966
51966 precisa de 16 bits.
binário: 1100101011111110
hexadecimal: cafe
octal: 145376

./bases_numericas.out 987654321
987654321 precisa de 30 bits.
binário: 111010110111100110100010110001
hexadecimal: 3ade68b1
octal: 7267464261

quinta-feira, 6 de setembro de 2012

Script para organizar a conjugação de verbos

Procurando ajudar uma colega taiwanesa que está se adaptando à nossa língua-pátria, eu respondo os e-mails mostrando a conjugação dos verbos para que ela entenda a concondância do pronome com a flexão do verbo.

Antes é necessário instalar o pacote brazilian-conjugate. O aplicativo apt-get instala o pacote através da linha de comando:

$ apt-get install brazilian-conjugate

Uma vez instalado, para chamar o aplicativo, digite:

$ conjugue

A figura abaixo mostra a tela assim que o programa inicia e em destaque vemos o comando que executa o conjugue bem como o verbo escolhido para ser conjugado (extorquir).


Figura 1. Tela Inicial do conjugue

Esta outra figura mostra a conjugação. Perceba que o programa reconhece os verbos defectivos e omite em certos pronomes.


Figura 2. Selecionando os tempos verbais

Note que o texto selecionado será copiado para área de memória e será usado como entrada para o script a seguir.

#!/bin/bash
# Created in September/02/2012

if [ "$#" -eq 0 ]
  then
    echo Falta o parâmetro dos verbos
  else
    conj1=`echo $1 | tr ":" " " | cut -f1 -d" "`
    conj3=`echo $1 | tr ":" " " | cut -f3 -d" "`
    conj4=`echo $1 | tr ":" " " | cut -f4 -d" "`
    conj6=`echo $1 | tr ":" " " | cut -f6 -d" "`

    echo eu $conj1
    echo ele/você $conj3
    echo nós $conj4
    echo eles/vocês $conj6
fi

Primeiro o script verifica se recebeu uma entrada ao ser chamado na linha de comando. Caso sim, as variáveis conj1, conj2, conj4 e conj6 associarão às flexões dos pronomes eu, ele, nós, eles respectivamente. Em seguida o echo imprime o pronome juntamente com o verbo flexionado. Como exemplo, vamos ver a saída do verbo extorquir no presente do indicativo:

./conjugador.sh :extorques:extorque:extorquimos:extorquis:extorquem
eu
ele/você extorque
nós extorquimos
eles/vocês extorquem

Repare que o script separa as flexões identificando o sinal de dois pontos (:). Assim, foram recebidos 5 parâmetros e reconhecido que não existe a primeira flexão.

Conclusão: Além de agilizar na orientação de como escrever corretamente, pode ser uma ferramenta de grande utilidade para evitar deslizes na língua portuguesa.

domingo, 5 de agosto de 2012

Planeje o futuro através das finanças

Apresento uma aplicação interessante na área de finanças e quem sabe pode despertar o seu perfil poupador. Trata-se da quantia que você pode juntar fazendo depósitos regulares sob uma taxa de juros contante durante um determinado número de períodos.

Após a exibição dos conteúdos de cada arquivo, veja uma demonstração com base nos dados compatíveis com os índices atuais da economia brasileira (agosto/2012). Por exemplo:

  1. Valor do depósito a cada mês: R$ 100,00
  2. Taxa de juros (valor percentual): 0,5% de acordo com este link.
  3. Período: 240 meses = 20 anos

Como sempre nos códigos-fontes de C++, divide-se em 3 arquivos:

  1. Definição da classe
  2. Definições das funções-membros da classe
  3. Programa driver

1. Definição da classe

$ cat rendimento.h

#ifndef RENDIMENTO_H
#define RENDIMENTO_H

class rendimento {
public:
    rendimento();
    rendimento(const rendimento& orig);
    virtual ~rendimento();
    void calculo(int, float, float);
private:

};

#endif /* RENDIMENTO_H */

2. Definições das funções-membros da classe

$ cat rendimento.cpp

#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <cmath>
#include <iomanip>
using std::setw;
using std::fixed;
using std::setprecision;
#include "rendimento.h"

rendimento::rendimento() {
}

rendimento::rendimento(const rendimento& orig) {
}

rendimento::~rendimento() {
}

void rendimento::calculo(int periodo, float juros, float depositoRegular) {
    
    float montante;  
    
    for (int i=1; i<=periodo; i++)
    {
        montante=(1+juros)* (pow(1+juros,i)-1)*depositoRegular/juros;        
        cout << setw(3) << i << " " << fixed << setprecision(2) << setw(10) <<  montante << "   ";
        if (i%4==0)
            cout << endl;
    }
}

3. Programa driver

$ cat main.cpp

#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include "rendimento.h"

int main(int argc, char** argv) {
    
    int tempo;
    float taxa, valorInicial, depositoRegular;
    
    cout << "Digite o valor depositado regular: ";
    cin >> depositoRegular;
    cout << "Digite a taxa de juros (em porcento): ";
    cin >> taxa;
    cout << "Digite o período de rendimentos: ";
    cin >> tempo;
    
    taxa/=100.0;
    
    rendimento mycalculo;
    mycalculo.calculo(tempo, taxa, depositoRegular);

    return 0;
}

Demonstração do resultado:

./caderneta_poupanca 
Digite o valor depositado regular: 100 
Digite a taxa de juros (em porcento): 0.5
Digite o período de rendimentos: 240
  1     100.50     2     201.50     3     303.01     4     405.03   
  5     507.55     6     610.59     7     714.14     8     818.21   
  9     922.80    10    1027.92    11    1133.56    12    1239.72   
 13    1346.42    14    1453.65    15    1561.42    16    1669.73   
 17    1778.58    18    1887.97    19    1997.91    20    2108.40   
 21    2219.44    22    2331.04    23    2443.20    24    2555.91   
 25    2669.19    26    2783.04    27    2897.45    28    3012.44   
 29    3128.00    30    3244.14    31    3360.86    32    3478.17   
 33    3596.06    34    3714.54    35    3833.61    36    3953.28   
 37    4073.54    38    4194.41    39    4315.88    40    4437.96   
 41    4560.65    42    4683.96    43    4807.88    44    4932.42   
 45    5057.58    46    5183.37    47    5309.78    48    5436.83   
 49    5564.52    50    5692.84    51    5821.80    52    5951.41   
 53    6081.67    54    6212.58    55    6344.14    56    6476.36   
 57    6609.24    58    6742.79    59    6877.00    60    7011.89   
 61    7147.45    62    7283.68    63    7420.60    64    7558.21   
 65    7696.50    66    7835.48    67    7975.16    68    8115.53   
 69    8256.61    70    8398.39    71    8540.89    72    8684.09   
 73    8828.01    74    8972.65    75    9118.01    76    9264.10   
 77    9410.92    78    9558.48    79    9706.77    80    9855.80   
 81   10005.58    82   10156.11    83   10307.39    84   10459.43   
 85   10612.23    86   10765.79    87   10920.12    88   11075.22   
 89   11231.09    90   11387.75    91   11545.19    92   11703.41   
 93   11862.43    94   12022.24    95   12182.85    96   12344.27   
 97   12506.49    98   12669.52    99   12833.37   100   12998.04   
101   13163.53   102   13329.84   103   13496.99   104   13664.98   
105   13833.80   106   14003.47   107   14173.99   108   14345.36   
109   14517.59   110   14690.67   111   14864.63   112   15039.45   
113   15215.15   114   15391.72   115   15569.18   116   15747.53   
117   15926.77   118   16106.90   119   16287.93   120   16469.88   
121   16652.72   122   16836.49   123   17021.17   124   17206.78   
125   17393.31   126   17580.78   127   17769.18   128   17958.53   
129   18148.82   130   18340.06   131   18532.26   132   18725.42   
133   18919.55   134   19114.65   135   19310.72   136   19507.78   
137   19705.81   138   19904.84   139   20104.87   140   20305.89   
141   20507.92   142   20710.96   143   20915.02   144   21120.09   
145   21326.19   146   21533.32   147   21741.49   148   21950.70   
149   22160.95   150   22372.26   151   22584.62   152   22798.04   
153   23012.53   154   23228.09   155   23444.73   156   23662.46   
157   23881.27   158   24101.18   159   24322.18   160   24544.29   
161   24767.51   162   24991.85   163   25217.31   164   25443.90   
165   25671.62   166   25900.47   167   26130.48   168   26361.63   
169   26593.94   170   26827.41   171   27062.04   172   27297.85   
173   27534.84   174   27773.02   175   28012.38   176   28252.94   
177   28494.71   178   28737.68   179   28981.87   180   29227.28   
181   29473.92   182   29721.79   183   29970.89   184   30221.25   
185   30472.86   186   30725.72   187   30979.85   188   31235.25   
189   31491.92   190   31749.88   191   32009.13   192   32269.68   
193   32531.53   194   32794.68   195   33059.16   196   33324.95   
197   33592.08   198   33860.54   199   34130.34   200   34401.49   
201   34674.00   202   34947.87   203   35223.11   204   35499.73   
205   35777.73   206   36057.11   207   36337.90   208   36620.09   
209   36903.69   210   37188.71   211   37475.15   212   37763.03   
213   38052.34   214   38343.10   215   38635.32   216   38929.00   
217   39224.14   218   39520.76   219   39818.86   220   40118.46   
221   40419.55   222   40722.15   223   41026.26   224   41331.89   
225   41639.05   226   41947.75   227   42257.98   228   42569.77   
229   42883.12   230   43198.04   231   43514.53   232   43832.60   
233   44152.27   234   44473.53   235   44796.39   236   45120.88   
237   45446.98   238   45774.71   239   46104.09   240   46435.11   

Considerações finais:

Os códigos-fontes foram escritos através da IDE Netbeans.

Caso prefira colar os respectivos conteúdo nos três arquivos com os nomes sugeridos, a linha de comando é:

$ g++ rendimento.cpp main.cpp -o caderneta_poupanca.out -ansi

O cálculo pode ser conferido através do BCB - Calculadora do cidadão.

Planeje seu futuro! Este programa pode auxiliar como lidar com o seu investimento.

quarta-feira, 18 de julho de 2012

Algoritmo do CPF

Achei interessante o algoritmo dos dígitos verificadores do CPF (Cadastro de Pessoa Física) e apresento o código-fonte em C++.

Para gerar o binário é necessário 3 arquivos:

  1. Definição da classe
  2. Definições das funções-membros da classe
  3. Programa driver

1. Definição da classe

$ cat Cpfnum.h

#ifndef CPFNUM_H 
#define CPFNUM_H 

class Cpfnum { 
public: 
    Cpfnum(); 
    Cpfnum(const Cpfnum& orig); 
    virtual ~Cpfnum();
    int PrimeiroDigito(int, int, int, int, int ,int ,int, int, int);
    int SegundoDigito (int, int, int, int, int ,int ,int, int, int, int);
private:


#endif /* CPFNUM_H */

2. Definições das funções-membros da classe

$ cat Cpfnum.cpp

#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <cstring>
using std::string;

#include "Cpfnum.h"

Cpfnum::Cpfnum() {
}

Cpfnum::Cpfnum(const Cpfnum& orig) {
}

Cpfnum::~Cpfnum() {
}

int Cpfnum::PrimeiroDigito(int v1,int v2,int v3,int v4,int v5,int v6,int v7,int v8,int v9)
{
  int m1, m2, m3, m4, m5, m6, m7, m8, m9; // multiplicado    
  int soma, resto, v10; 
  
  m1=v1*10;
  m2=v2*9;
  m3=v3*8;
  m4=v4*7;
  m5=v5*6;
  m6=v6*5;
  m7=v7*4;
  m8=v8*3;
  m9=v9*2;
  
// somando m1 a m9
  soma=m1+m2+m3+m4+m5+m6+m7+m8+m9;

// obtendo o 1° dígito verificador: divisão da soma por 11 e o resto é o 1° dígito verificador
    resto=soma%11;
    if (resto < 2)
      v10=0;
    else
      v10=11-resto;
    
    return v10;
}

int Cpfnum::SegundoDigito (int v1,int v2,int v3,int v4,int v5,int v6,int v7,int v8,int v9, int v10)
{
  int m1, m2, m3, m4, m5, m6, m7, m8, m9, m10; // multiplicado
  int soma, resto, v11;

// novos valores multiplicados após encontrar o 1° dígito verificador
   m1=v1*11;
   m2=v2*10;
   m3=v3*9;
   m4=v4*8;
   m5=v5*7;
   m6=v6*6;
   m7=v7*5;
   m8=v8*4;
   m9=v9*3;
   m10=v10*2;

// somando m1 a m10
    soma=m1+m2+m3+m4+m5+m6+m7+m8+m9+m10;

// divisão da soma por 11. Aplica-se regra do resto para encontrar o 2° dígito verificador
    resto=soma%11;
    if (resto < 2)
      v11=0;
    else
      v11=11-resto;

    return v11;
}

3. Programa driver

$ cat main.cpp

#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <cstring>
using std::string;
#include <sstream>
using std::stringstream;
#include <cstdlib>

#include "Cpfnum.h"

//using namespace std;

int main(int argc, char** argv) {
    
  string mystring;
  string sv1, sv2, sv3, sv4, sv5, sv6, sv7, sv8, sv9, sv10, sv11; // sv10 = 1° dígito verificador e sv11 = 2° dígito verificador
  int v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11;  // valor
  int pdv, sdv; // primeiro e segundo digito verificador

  cout << "Entre com o número do CPF: ";
  cin >> mystring;

  sv1=mystring[0];
  sv2=mystring[1];
  sv3=mystring[2];
  sv4=mystring[3];
  sv5=mystring[4];
  sv6=mystring[5];
  sv7=mystring[6];
  sv8=mystring[7];
  sv9=mystring[8];

  stringstream(sv1) >> v1;
  stringstream(sv2) >> v2;
  stringstream(sv3) >> v3;
  stringstream(sv4) >> v4;
  stringstream(sv5) >> v5;
  stringstream(sv6) >> v6;
  stringstream(sv7) >> v7;
  stringstream(sv8) >> v8;
  stringstream(sv9) >> v9;

  if (mystring.length() < 9 || mystring.length() == 10 || mystring.length() > 11)
    cout << "Você digitou " << mystring.length() << " caracteres. Digite 9 ou 11." << endl;

  Cpfnum myCpfnum;
  myCpfnum.PrimeiroDigito(v1, v2, v3, v4, v5, v6, v7, v8, v9);
  myCpfnum.SegundoDigito(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10);
  
  if (mystring.length() == 9)
  {
    v10=myCpfnum.PrimeiroDigito (v1, v2, v3, v4, v5, v6, v7, v8, v9);
    v11=myCpfnum.SegundoDigito (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10);
    cout << v1 << v2 << v3 << v4 << v5 << v6 << v7 << v8 << v9 << "-" << v10 << v11 << endl;
  }
  
  if (mystring.length() == 11)
  {
    pdv=myCpfnum.PrimeiroDigito (v1, v2, v3, v4, v5, v6, v7, v8, v9);
    sdv=myCpfnum.SegundoDigito (v1, v2, v3, v4, v5, v6, v7, v8, v9, pdv);

    sv10=mystring[9];
    sv11=mystring[10];
    stringstream(sv10) >> v10;  
    stringstream(sv11) >> v11;

    if ( (v10 == pdv ) && (v11 == sdv ) )
      cout << "CPF válido!" << endl;
    else
      cout << "CPF inválido" << endl;
  }
  
  return 0;
}

Considerações finais:

Uma IDE (Integrated Development Environment) faz muita diferença no desenvolvimento. Meus primeiros programas foram elaborados com o Anjuta, mas passei a usar o NetBeans.

O Anjuta cria as classes sem muitas instruções (virtual) o que considero bom para começar o contato com C++. No entanto, nada impede de iniciar com NetBeans e ignorar algumas funções-membros.

As IDEs vem com as configurações que buscam o compilador para gerar o binário. Caso prefira colar os respectivos conteúdo nos três arquivos com os nomes sugeridos, a linha de comando é:

$ g++ Cpfnum.cpp main.cpp -o cpf.out -ansi

E para escrever este texto usei o BlueFish. Claro que não deixei de usar o VIM, principalmente porque um recurso essencial como colar em colunas só encontro nele.

sábado, 16 de junho de 2012

Simplificação do código para ser otimizado


Um problema de matemática chamou-me a atenção e encontrei a solução usando a soma de uma P.A. O enunciado é este:


Seja
f(n)=n se n<10
f(n)=multiplicação dos algarismos se n>=10
Então f(1)+f(2)+f(3)+...+f(100) é igual a?

Decidi fazer um programa e o principal deste texto não é o programa que resolve este problema. É como o conhecimento pode simplificar o processamento e resolver em menos tempo além de comparar o desempenho de duas linguagens de programação.

Primeiro foi feito em shell script. No bloco for i in `seq 10 1 99` existem duas variáveis que armazenam os algarismos do número. O comando cut -c 1 associa a dezena à variável valor1 e cut -c 2 associa a unidade à variável valor2. A variável multiplicado armazena o produto enquanto que soma acumula os resultados de multiplicado.


#!/bin/bash 

for i in `seq 9`
   do 
      let soma1=$soma1+$i  
   done  
 
for i in `seq 10 1 99`  
   do  
      valor1=`echo $i | cut -c 1`  
      valor2=`echo $i | cut -c 2` 
      multiplicado=`echo "$valor1 * $valor2" | bc`  
      let soma2=$soma2+$multiplicado  
   done 
  
let soma=$soma1+$soma2 echo Resultado $soma

Executando o script junto com o comando time tenho a resposta que levou para efetuar os cálculos:

 

 
Resultado 2070

real 0m0.704s
user 0m0.036s
sys 0m0.028s

Encontrada a solução em uma linguagem, quis testar em C++. No entanto como não consegui separar as dezenas e unidades em duas variáveis, encontrei uma solução mais simples. E para que a comparação seja válida, é preciso que os programas executem as mesmas rotinas.

Usando dois laços for separam-se as dezenas e unidades. A otimização em shell script é apresentada abaixo:

   
#!/bin/bash  

for i in `seq 9`
   do  
      let soma1=$soma1+$i  
   done  

for dezena in `seq 9`  
  do  
    for unidade in `seq 9`  
      do  
        resultado=$dezena*$unidade  
        let soma2=$soma2+$resultado 
      done  
  done  

let soma=$soma1+$soma2  
echo Resultado $soma  


Resultado 2070

real 0m0.041s
user 0m0.004s
sys 0m0.012s

Por fim, testa-se em C++.

Como foi dito, elaborei a lógica deste código antes do segundo shell script. As explicações são as mesmas do código anterior.

 
# include <iostream>  
using namespace std;  
int main()  
{  
   int dezena, unidade;  
   int soma1=0, soma2=0;
  
   for (int i=1; i<10; i++)  
      soma1+=i;  

   for (dezena=1; dezena<10; dezena++) 
   {  
      for (unidade=1; unidade<10; unidade++) 
      { 
        soma2+=dezena*unidade; 
      } 
   } 
 
   cout << "Resultado " << soma1+soma2; 
   cout << endl; 
 
   return 0; 
}  


Resultado 2070

real 0m0.004s
user 0m0.000s
sys 0m0.000s


Resumo dos tempos:

Shell Script Shell Script (com otimização) C++
0.704s 0.041s 0.004s

Conclusão: cada linguagem tem a sua particularidade. Para desenvolver algo rápido considero que o shell script é uma ferramenta que atende muito bem. Por outro lado, se for preciso alto desempenho, o C++ é insuperável*. Adicionalmente, fica claro que o resultado do que é compilado é mais rápido do que interpretado.
* De acordo com o professor doutor José Luis Zem da disciplina de Arquitetura e Organização de Computadores, a linguagem Fortran tem desempenho superior além de maior capacidade de ponto flutuante.

Agradeço ao professor Zem por explicar a diferença de desempenho entre compilado e interpretado. No caso do interpretado há um outro programa analisando cada linha do script e transformando em instruções de computador. No caso dos compilados, o compilador usa regras de otimização para gerar o binário.

domingo, 13 de maio de 2012

Desligar computador se o download não terminar

  No código-fonte desta publicação tive que adaptar o código que está em Desligando o micro ao terminar o download.
  Sempre funcionou bem, mas foi preciso pensar numa situação de contorno quando a conexão caia ou quando o roteador wireless dava seus tilts. Neste caso, o download não se completa e a condição test -s "$inteiro" não passa para verdadeiro.
  Foi pensado da seguinte forma: comparo a quantidade de bytes entre 2 segundos consecutivos.
  Se não forem iguais a variável contagem sofre um reset voltando a valer 1 (um). Se forem iguais a variável contagem é incrementada de 1 a cada 1 segundo. Se a contagem chegar a 300 (5 minutos), é executado o comando para desligar.
  Alguns downloads não admitem continuar de onde pararam e talvez seja melhor desligar o computador tão logo que se perceba que o download não será concluído.


#!/bin/bash
# v1.0: 10/21/2006
# v1.1: 04/11/2012
# v1.2: 05/12/2012

parte=""
inteiro=""

contagem=0
until test -s "$inteiro"
  do
   status_antes=`du "$parte" | awk '{printf "%2s\n",$1}'`
   sleep 1
   status_depois=`du "$parte" | awk '{printf "%2s\n",$1}'`

   if [ "$status_antes" -ne "$status_depois" ]
    then
     contagem=1
   else
    let contagem=$contagem+1
     if [ "$contagem" -eq 300 ]
      then
       /sbin/shutdown -h now
     fi
   fi

   echo Download em andamento: $status_depois kB $contagem
   sleep 2
   continue
  done

test -s "$inteiro"
  /sbin/shutdown -h now

sexta-feira, 6 de abril de 2012

Desligando o micro ao terminar o download

   O script que apresento é uma tarefa automática que desliga o computador imediatamente após o último byte do seu download chegar. Deixo claro que só serve se for usado através do gerenciador de downloads do firefox como na figura abaixo:

   A demonstração será feita com o download "LACUNA COIL - Enjoy The Silence.flv" que aparece no topo da lista. Adapte para situações que você for baixar algo que não queira ficar esperando.

   É necessário subtituir as variáveis parte e inteiro pelo nome do arquivo que está baixando. Recomendo ir no diretório que o gerenciador baixa e com o mouse copie o nome do arquivo e cole como no exemplo do script abaixo.

   Como o gerenciador cria dois arquivos (nome.extensão e nome.extensão.part), a grande sacada é testar se nome.extensão é diferente de zero byte. Somente ao terminar nome.extensão.part o tamanho é transferido para nome.extensão deixando de ser um arquivo vazio.

   O comando until testa se nome.extensão deixou de ser um arquivo vazio. Enquanto isso não sai desta condição, é exibido o tamanho do arquivo a cada 2 segundos através do comando sleep. O comando awk que pega um campo específico (no caso o tamanho do arquivo) é usando para a variável parte.

   Terminado o loop until existe outro test que verifica se o arquivo deixou de ter zero byte e o shutdown entra em ação. Por esta razão, o script tem que ser executado pelo root.

!/bin/bash
# v1.0: 10/21/2006
# v1.1: 04/11/2012

parte="LACUNA COIL - Enjoy The Silence.flv.part"
inteiro="LACUNA COIL - Enjoy The Silence.flv"

until test -s "$inteiro"
  do
   status=`du "$parte" | awk '{printf "%2s\n",$1}'`
   echo Download em andamento: $status kB
   sleep 2
   continue
  done

test -s "$inteiro"
   /sbin/shutdown -h now