You are currently browsing Thobias Salazar Trevisan's articles.

Palavras-chave: shell, convert, ImageMagick, redimensionar, resize, thumbnail, imagem, foto

O ImageMagick é um conjunto de softwares para manipular vários formatos de imagens. Esta dica aborda como redimensionar imagens.

Dentre os programas do ImageMagick está o comando convert, que possui várias opções para manipular imagens. Para redimensionar utilizamos a seguinte sintaxe:

convert -resize <largura>x<altura> arquivo_original arquivo_novo

Exemplo prático: Criar um thumbnail do arquivo imagem.jpg.

convert -resize 120x120 imagem.jpg thumbnail_imagem.jpg

Pode-se ainda redimensionar a imagem e, ao mesmo tempo, converter para outro formato. Por exemplo, criar o thumbnail como PNG:

convert -resize 120x120 imagem.jpg thumbnail_imagem.png

Como último exemplo, um script que cria thumbnails para todos os arquivos JPG do diretório corrente e cria uma página HTML para visualizar as imagens:

#!/bin/bash

for i in *.jpg; do
  echo "Gerando thumbnail da imagem $i..."
  convert -resize 120x120 $i thumbnail_$i
  echo "<a href=\"$i\"> <img src=\"thumbnail_$i\"> </a>" >> index.html
done

Agora é só abrir o arquivo index.html no seu navegador favorito.

Mais detalhes: man convert

Palavras-chave: shell, variável dentro de variável, eval

Às vezes precisamos pegar o conteúdo de uma variável cujo nome está contido em outra variável. Será mostrado algumas maneiras de realizar esta tarefa:

$ A=XXX
$ B=A
$ echo $B
A
$ echo ${!B}
XXX
$ eval echo \\$$B
XXX
$ eval echo '$'$B
XXX

Exemplo prático:

#!/bin/bash

VERDE="echo -en \\e[1;32m"
AZUL="echo -en \\e[1;36m"
VERMELHO="echo -en \\e[1;31m"
NORMAL="echo -en \\e[0;39m"

# função que imprime um texto colorido
imprime_colorido() {
   eval \\$$1   # seta para a cor passada (primeiro parâmetro)
   shift
   echo $*     # imprime o texto
   $NORMAL     # volta para a cor padrão
}

imprime_colorido VERDE texto em verde
imprime_colorido AZUL texto em azul
imprime_colorido VERMELHO texto em vermelho

Outra situação é quando precisamos obter o conteúdo de uma variável cujo pedaço do nome está contido em outra variável:

$ passo1=codificar
$ passo2=testar

$ i=1
$ eval echo \\$passo$i
codificar

$ i=2
$ eval echo '$passo'$i
testar

$ tmp=passo$i   # usando uma variável temporária
$ echo ${!tmp}
testar

$ for i in 1 2; do eval echo passo$i = '$passo'$i; done
passo1 = codificar
passo2 = testar

Palavras-chave: shell, Argument list too long, /bin/rm, /bin/mv, bash, ksh, sh

Sistemas operacionais UNIX normalmente têm um tamanho fixo de memória que pode ser utilizada para variáveis de ambiente e argumentos na chamada de um programa. Este tamanho varia de sistema operacional para sistema operacional. Para obter este valor pode-se executar o seguinte comando:

$ getconf ARG_MAX
131072

Quando executamos algum comando e passamos (incluindo o nome, o caminho do programa e variáveis de ambiente) uma quantidade de argumentos que supere o definido em ARG_MAX o programa é terminado com a seguinte mensagem:

shell: comando: Argument list too long

Vamos simular este comportamento criando uma grande quantidade de arquivos em um diretório. O número de arquivos que precisam ser criados pode variar de acordo com o tamanho definido em ARG_MAX.

$ for i in $(seq 1 50000); do touch $i; done
$ rm *
bash: /bin/rm: Argument list too long
$ ls *
bash: /bin/ls: Argument list too long
$ mv * /tmp/
/bin/bash: /bin/mv: Argument list too long
$ grep a *
bash: /bin/grep: Argument list too long
$ chmod 555 *
bash: /bin/chmod: Argument list too long

Existem várias maneiras de contornar este “problema”. Serão listadas algumas:

$ find . -name '*' -print0 | xargs -0 rm
$ find . -type f -print0 | xargs -0 rm
$ find . -type f -exec rm {} \\;
$ echo * | xargs rm

Dica: usando o xargs é mais rápido!

Um leitor mais atendo notaria que a última solução apresentada não poderia funcionar, já que o * utilizado seria expandido para todos os arquivos e excederia o tamanho definido em ARG_MAX.

O echo é um comando builtin do shell, ou seja, um novo programa não é executado (chamada de sistema exec não é invocada). Se utilizarmos o comando echo do sistema operacional o erro será mostrado:

$ /bin/echo *
bash: /bin/echo: Argument list too long
$ echo *
lista de todos os arquivos do diretório

A solução com echo não funciona se existir espaços em branco no nome dos arquivos.

Palavras-chave: shell, datas, date, awk, unix timestamp, posix time, unix time, unix epoch

Maneiras rápidas de converter de Unix timestamp para um formato mais amigável:

GNU date
date -d '1/1/1970 + 1158857787 seconds'
date -d '1/1/1970 + 1158857787 seconds' '+%d/%m/%Y %H:%M:%S %z'
BSD date
date -r 1158857787
GNU Awk
echo 1158857787 | awk '{print strftime("%c",$1)}'
awk 'BEGIN {print strftime("%c",1158857787)}'
awk 'BEGIN {print strftime("%d/%m/%Y %H:%M:%S %z",1158857787)}'

Para fazer o caminho inverso, a partir de uma data gerar o Unix timestamp:

GNU e BSD date
date +%s   # unix timestamp de agora
GNU date
date -d '09/21/2006 13:56:27' +%s   # de uma data específica
GNU Awk
awk 'BEGIN {print mktime("2006 09 21 13 56 27")}'

Observação: Você pode ter diferença de algumas horas dependendo do seu timezone.

Add to Technorati Favorites

Assuntos