Pages

Saturday, December 22, 2007

Shell-script: trabalhando com extensões em scripts

Imprevistos realmente incríveis me impediram de ler tópicos atrasados e revisar os comentários como eu prometi. Me desculpem. Em todo caso isso já não é (ou melhor, "não pode ser") mais uma grande desculpa.

Bom. A questão que apresento aqui deve ter várias soluções, eu uso a mais prática delas de acordo com o meu conhecimento sobre shell-script (e também por ser única solução que eu conheço).

O problema se apresenta em diversos casos, vou exemplificar através de uma conversão entre formatos de imagem. Vamos colocar o problema sobre a ótica de quem quer converter vários arquivos png em imagem .eps. Quem escreve em LaTeX está vislumbrando um motivo, quem não escreve, ignore o motivo, pense como um problema qualquer que precisa de solução que será útil em outros casos do seu próprio interesse.

Utilizando o aplicativo "convert" pode-se converter um arquivo da seguinte forma.

convert arquivo.png arquivo.eps

O problema é se você tiver vários arquivos a serem convertidos. Como disse, para cada aplicativo/função existe algumas soluções. A minha consiste em criar um script com a seguinte função.

#!/bin/bash
num=$(echo $1 |wc -c)
fim=$(($num-5))
NAME="$(echo $1|cut -b -$fim)"

convert "$1" "$NAME.eps"


A parte em negrito é a chave da questão. Ela remove os três últimos caracteres do input "$1" permitindo utilizar o mesmo no comando com uma nova extensão. Mas essa solução resolve apenas um problema. Como converter o arquivo.png em arquivo.eps utilizando apenas o comando meuscript arquivo.png. A segunda parte consiste em colocar um comando com o find, tipo

find ./ -maxdepth 1 -type f -iname \*png -exec ~/bin/img2eps '{}' \;

Observe que meu exemplo é muito simples. Você pode modificar ele a vontade para converter entre diferentes formatos de imagem (png para jpg, por exemplo, utilizando o próprio convert), converter wavs para mp3 (com o lame), ou mp3 para ogg (com o ogg123), pdfs para imagens (com o pdfimage ou também com o convert) e milhares de outras funções que você queira que trabalhe em lote.

Bom, mas quem não conhece ou não usa muito o find deve estar pensando por eu fiz tudo isso. Porque eu não usei o comando diretamente no find, tipo:

find ./ -maxdepth 1 -type f -iname \*png -exec convert '{}' '{}.eps' \;

O motivo é que o resultado do comando acima gera arquivos com o nome arquivo.png.eps e não arquivo.eps. Ok, você pode fazer isso desse jeito mesmo e depois usar um renomeador de arquivos em lote e resolver o problema da "extensão dupla". Mas também pode usar a solução que eu apresento. A liberdade de escolha sempre foi e será a máxima dos usuários linux.

Outro detalhe, é que novamente a gente volta a questão do "exemplo". No exemplo, eu dei a entender que é preciso colocar um comando dentro de um script e chamar outro comando dentro de uma linha grande e chata ou dentro de um segundo script. Tudo bem, você pode fazer isso, mas também pode colocar o "núcleo de conversão" dentro de uma função e usar o find para chamar essa função e não um outro script. Na verdade, na verdade as opções apesar de discretas são quase infinitas. Não vale apena ficar vislumbrando possibilidades por si só.

O que vale apena o destaque aqui (também por ser o objetivo desse texto) são as três linhas mágicas abaixo.

num=$(echo $1 |wc -c)
fim=$(($num-5))
NAME="$(echo $1|cut -b -$fim)"


O como, o onde e o porque você utilizará esse pedaço de código eu deixo com cada um. Posso afirmar apenas que ele me é muito útil. E imagino que ele possa ser útil a várias outras pessoas também.

OBS.: a opção '-maxdepth 1' no find faz com que a busca se limite a diretório raíz mencionado, que nos exemplos acima foi o "diretório atual" './', a utilização de outros valores de "-maxdepth" ou mesmo ignorá-lo dependerá de como o script foi escrito ou o objetivo dele. Nos exemplos acima qualquer valor seria possível, mas perigoso, vai que alguém iniciante digite esses comando no diretório home sem saber o que ele faz ? Do jeito que eu apresentei o problema os riscos praticamente não existem, por isso eu usei '-maxdepth 1'.

OBS.2: sei que devem existir várias pessoas que imaginem ter outras soluções melhores para esse problema. Essa solução que eu apresentei fui eu mesmo que rascunhei, pode não ser nenhuma novidade para algumas pessoas e nem a melhor forma de resolver o problema, mas não imagina como eu demorei (8 anos !!!) para ter uma solução dessas comigo. Então se quiserem compartilhar soluções para essa questão, bem, sou todo ouvidos ("e olhos") ...

No comments:

Post a Comment