Tenho uma base de dados que contém dados de trabalhos enviados a um evento. Além disso, possuo em um diretório os trabalhos em .rtf.
O que preciso fazer? Converter cada um dos trabalhos para .pdf e inserir no cabeçalho uma imagem do evento com seu ISSN. Além disso, a partir da área, título do trabalho, palavras-chave e autores, preciso gerar uma base de dados em um formato criado por nós para fazer buscas através de javascript nos anais do evento. Para isso, fiz um script que cuida dessas duas coisas.
Como fazia tempo que não mexia com bash script, estava meio enferrujado, mas nada que uma pesquisa no Google não ajude.
Consultei os dados do banco usando SQL e exportei o resultado para um arquivo CSV delimitado por TABs.
Aproveitei a estrutura para ler arquivos apresentadas por: http://bash.cyberciti.biz/file-management/read-a-file-line-by-line/
Além disso, para padronizar o nome dos arquivos, converti todas as informações para maiúsculo, sendo que em alguns lugares precisei retirar o acento das palavras, mas mais uma vez tive uma ajudinha: http://ubuntuforums.org/showthread.php?p=6641997
Porém a conversão das letras com acento não funcionou. Poderia ter aberto o arquivo no OpenOffice e convertido, porém acreditei que existiria um jeito de fazer isso no terminal e depois de muito procurar encontrei a solução: http://wjd.nu/notes/2009. Também vou transcrevê-la para não perdé-la, pois o site não dá nenhuma link direto a ela:
Python has excellent Unicode support. Most of the time
it just works. However, when you want to redirect non-ASCII characters to a different program through shell redirection, you will run into a
UnicodeEncodeError
.
See the following example:
$ locale | grep LC_CTYPE
LC_CTYPE="en_US.UTF-8"
$ python -c 'print "\u20ac 3.50"'
\u20ac 3.50
$ python -c 'print u"\u20ac 3.50"'
€ 3.50
$ python -c 'print u"\u20ac 3.50"' | cat
Traceback (most recent call last):
File "", line 1, in
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
Python calls something like
isatty(3)
("is a TTY?") on the
standard out file descriptor, and when that returns 0 (false) it forces
stdout
to use the
ascii
codec. This can be quite annoying if you want to use other shell tools (
awk(1)
,
grep(1)
,
sed(1)
,
tr(1)
etc..) to quickly search through or modify the output stream.
The solution is to replace the
stdout
object with one that doesn't assume that a non-terminal only likes ASCII. Add the following to your python code:
import codecs, locale, sys
sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, 'replace')
It's not real pretty, but it works :-)
$ python -c 'import codecs, locale, sys
> sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, "replace")
> print u"\u20ac 3.50"' | cat
€ 3.50
Escrevi/copiei uma macro n{d}o OpenOffice para converter os arquivo .rtf para .pdf e adicionar o cabeçalho com as informações do evento (esta parte me tomou bastante tempo, pois apesar de existir bastante informação de como modificar o cabeçalho e como inserir uma imagem através de macros, esta parte não funcionou no OOo 3.0 disponibilizado pelo GSB para o Slackware, quer dizer, o programa travava 99,9% das vezes e até eu perceber isso, achei que estava fazendo alguma coisa errada. No OOo 2.4 também disponiblizado pelo GSB o programa trava 0.01%. Ainda vou tentar descobrir porque!): http://www.oooforum.org/forum/viewtopic.phtml?t=3772
Sub test( cArg )
Print "|"+cArg+"|"
End Sub
Sub ConvertWordToPDF( cFile )
cURL = ConvertToURL( cFile )
' Open the document.
' Just blindly assume that the document is of a type that OOo will
' correctly recognize and open -- without specifying an import filter.
oDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0, Array(MakePropertyValue( "Hidden", True )))
oGraph = oDoc.createInstance("com.sun.star.text.GraphicObject")
With oGraph
.GraphicURL = "file:///home/cerodrigues/kadu.jpg"
.AnchorType = com.sun.star.text.TextContentAnchorType.AS_CHARACTER
.Width = 6000
.Height = 6000
End With
oEstPagina = oDoc.StyleFamilies.getByName("PageStyles")
oPagPadrao = oEstPagina("Default")
oPagPadrao.HeaderIsOn = True
oTxtCabecalho = oPagPadrao.HeaderText
oCursorCabecalho = oTxtCabecalho.createTextCursor()
oTxtCabecalho.insertTextContent(oCursorCabecalho, oGraph, False)
'oText.insertTextContent( oCursor, oGraph, False )
cFile = Left( cFile, Len( cFile ) - 4 ) + ".pdf"
cURL = ConvertToURL( cFile )
' Save the document using a filter.
oDoc.storeToURL( cURL, Array(MakePropertyValue( "FilterName", "writer_pdf_Export" ),)
oDoc.close( True )
End Sub
Function MakePropertyValue( Optional cName As String, Optional uValue ) As com.sun.star.beans.PropertyValue
Dim oPropertyValue As New com.sun.star.beans.PropertyValue
If Not IsMissing( cName ) Then
oPropertyValue.Name = cName
EndIf
If Not IsMissing( uValue ) Then
oPropertyValue.Value = uValue
EndIf
MakePropertyValue() = oPropertyValue
End Function
Por fim, o script final ficou assim:
#!/bin/bash
# Código utilizado para consulta através do JS
# "área^diretório onde está o artigo/nome do arquivo sem extensão*título do arquivo|palavras chaves separadas por vírgula (final),$autor1@autor2@~"
rm sucesso.txt > /dev/null 2>&1
rm fracasso.txt > /dev/null 2>&1
COD_PROCESSADO=0
AREA_PROCESSADO=""
FCOUNT=0
AREA=""
NOVO="y"
FILE="./list_trabalhos_com_oral.csv"
toUpper() {
echo -n $1 | python -c 'import sys, locale, codecs; sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, "replace"); print( sys.stdin.read().decode("utf8").upper() )'
}
# Coloca a descrição da forma de apresentação em minúsculo, tira os acentos, remove o início do texto "Sessão de " e substitui os espaços por _ e remove qualquer caracter de controle
processFrmApr() {
echo -n $1 | python -c 'import sys, locale, codecs; sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, "replace"); print( sys.stdin.read().decode("utf8").lower() )' | unaccent utf-8 | sed 's,sessao de ,,' | sed 's, ,_,g' | sed 's,[[:cntrl:]],,g'
}
# Coloca a descrição da área de conhecimento em minúsculo, tira os acentos e substitui os espaços por _ e remove qualquer caracter de controle
processArCnh() {
echo -n $1 | python -c 'import sys, locale, codecs; sys.stdout = codecs.getwriter(locale.getdefaultlocale()[1])(sys.stdout, "replace"); print( sys.stdin.read().decode("utf8").lower() )' | unaccent utf-8 | sed 's, ,_,g' | sed 's,[[:cntrl:]],,g'
}
# Descrição dos campos em FIELDS
# FIELDS[1] = Código do Banco de Dados
# FIELDS[2] = Título do Trabalho
# FIELDS[3] = Nome do Arquivo
# FIELDS[4] = Palavras Chaves separadas por ;
# FIELDS[5] = Autor
# FIELDS[6] = Área de conhecimento
# FIELDS[7] = Tipo do Trabalho
processLine () {
for i in `seq 1 7`;
do
FIELDS[$i]=$(toUpper `echo $line | awk -F'\t' '{print $'$i'}'`)
done
# Gera o PDF dos arquivos submetidos e o arquivo para ser utilizado na busca pelo javascript
# Se mudou a área que está sendo processada deve-se criar o arquivo que contêm os dados da área
echo ${FIELDS[6]}
if [ "x${FIELDS[6]}" != "x$AREA_PROCESSADO" ]; then
AREA_PROCESSADO=${FIELDS[6]}
# Termina o arquivo antigo
echo -n "~" >> $AREA.txt
AREA=$(processArCnh ${FIELDS[6]})
rm $AREA.txt > /dev/null 2>&1
touch $AREA.txt
NOVO="y"
fi
echo $AREA_antiga
# Se mudar o código é um novo trabalho, então faz a conversão para PDF e insere o cabeçalho do evento
# Se mudou o código do trabalho, finaliza esta entrada no texto utilizado pelo javascript e inicia a nova
if [ ${FIELDS[1]} != $COD_PROCESSADO ]; then
if [ $COD_PROCESSADO != 0 -a "x$NOVO" != "xy" ]; then
# Termina entrada apenas se não é a primeira mudança, pois o conteúdo anterior era vazio.
echo -n "~" >> $AREA.txt
fi
COD_PROCESSADO=${FIELDS[1]}
NOVO="x"
echo "Convertendo arquivo: "${FIELDS[3]}
# Cria pasta de comunicação oral ou painél se não existir
FIELDS[7]=$(processFrmApr ${FIELDS[7]})
echo -n ${FIELDS[7]}
if [ ! -d ${FIELDS[7]} ]; then
mkdir ${FIELDS[7]}
fi
# Cria a pasta da área de conhecimento do trabalho se não existir
FIELDS[6]=$(processArCnh ${FIELDS[6]})
if [ ! -d ${FIELDS[7]}/${FIELDS[6]} ]; then
mkdir ${FIELDS[7]}/${FIELDS[6]}
fi
# Converte o arquivo para pdf e inclui o cabeçalho do SEU
contador=1
FCOUNT=`expr $FCOUNT + 1`
while [ $contador -le 5 ]; do
if [ -f upload2009/${FIELDS[3]}.pdf ]; then
echo "Não é necessário converter"
echo "Copiando" ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
cp ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
break
fi
if [ -f upload2009/${FIELDS[3]}.rtf ]; then
echo "Iniciando conversão"
/usr/lib/ooo-2.4/program/soffice.bin -invisible -headless "macro:///rtf2pdf.Conversion.ConvertWordToPDF(`pwd`/upload2009/${FIELDS[3]}.rtf)"
# Arquivo convertido com sucesso
if [ $? == 0 ]; then
echo "Copiando" ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
cp ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
break
fi
else
echo "Não é necessário converter"
if [ -f upload2009/${FIELDS[3]}.pdf ]; then
echo "Copiando" ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
cp ./upload2009/${FIELDS[3]}.pdf ./${FIELDS[7]}/${FIELDS[6]}/$FCOUNT.pdf
break
fi
fi
contador=`expr $contador + 1`
done
if [ $contador -le 5 ]; then
echo ${FIELDS[2]} convertido com sucesso >> sucesso.txt
else
echo ${FIELDS[2]} não convertido >> fracasso.txt
fi
# Insere no arquivo utilizado pelo javascript os dados do trabalho
# Insere a área, o diretório onde está o artigo, o nome do artigo sem extensão e o título do artigo
echo -n $AREA_PROCESSADO"^"${FIELDS[7]}"/"${FIELDS[6]}"/"$FCOUNT"*"${FIELDS[2]}"|" >> $AREA.txt
# Insere as palavras chaves
for i in `seq 1 3`;
do
PC[$i]=$(toUpper `echo ${FIELDS[4]} | awk -F';' '{print $'$i'}'`)
echo -n ${PC[$i]}"," >> $AREA.txt
done
echo -n "$" >> $AREA.txt
# Insere o primeiro autor
echo -n ${FIELDS[5]}"@" >> $AREA.txt
# Insere os demais autores
else
echo -n ${FIELDS[5]}"@" >> $AREA.txt
fi
}
BAKIFS=$IFS
IFS=$(echo -en "\n\b")
exec 3<&0
exec 0<$FILE
while read line
do
# use $line variable to process line in processLine() function
processLine $line
done
exec 0<&3
# restore $IFS which was used to determine what the field separators are
IFS=$BAKIFS
exit 0
Muito legal esse monstrengo!!!