You are here:
Wiki-SL
>
TWikiBar Web
>
TWikiBarConversa007
(06 Feb 2008,
CollonsTorre
)
(raw view)
E
dit
A
ttach
---+!! Conversación de Bar Parte VII --- %TOC% --- - Como dijiste? Repite que no te entiendo! Se te derritieron los pensamientos para hacer el =scriptiziño= que te pedí? - Si, realmente tuve que colocar mucha materia gris en la pantalla, pero creo que lo conseguí! Bueno, por lo menos en los tests que hice la cosa funcionó, pero tu siempre me colocas piedras en el camino! - No sera tanto, programar en shell es muy fácil, lo que vale son los consejos y los detalles de programación que te doy, que no son triviales. Las correcciones que te hago, son justamente para mostrarlos. Pero vamos a pedir dos "chopps" y le echo una ojeada a tu script. - Mozo, trae dos. No te olvides que uno es sin espuma! --- %TERMINAL_INI% $ cat restaura %OUT_INI% #!/bin/bash # # Restaura archivos borrados vía erreeme # if [ $# -eq 0 ] then echo "Uso: $0 <Nombre del Archivo a Ser Restaurado>" exit 1 fi # Lee el nombre del directorio original en la última línea Dir=`tail -1 /tmp/$LOGNAME/$1` # O grep -v borra la última línea y crea el # archivo con directorio y nombres originales grep -v $Dir /tmp/$LOGNAME/$1 > $Dir/$1 # Borra el archivo que ya estaba moribundo rm /tmp/$LOGNAME/$1 %OUT_FIM% %TERMINAL_FIM% - Un momento, déjame ver se lo entendí. Primero colocas en la variable Dir la última línea del archivo cuyo nombre está formado por /tmp/nombre del operador ($LOGNAME)/parámetro pasado con el nombre del archivo a ser restaurado ($1). Enseguida el grep -v que montaste borra esa línea en que estaba el nombre del directorio, o sea, siempre es la última y manda lo que resta del archivo, que sería el archivo ya limpio, hacia el directorio original para después borrar el archivo del "cubo de la basura"; S E N S A C I O N A L! Impecable! Ningun error! Lo viste? ya le estás tomando las medidas al shell! - Entonces vamos a continuar, basta ya de bla-bla-bla, de que vas a hablar hoy? - Ah! estoy viendo que el bichito del Shell se te contagió. Que bueno, vamos a ver como se pueden (y deben) leer datos y formatear pantallas, pero primero vamos a conocer un comando que te da todas las herramientas para que formatees tu pantalla de entrada de datos. ---++ El comando tput Este comando se usa principalmente para posicionar el cursor en la pantalla, sin embargo también es muy usado para borrar datos de la pantalla, saber la cantidad de líneas y columnas de la pantalla, posicionar correctamente un campo, borrar un campo cuya entrada se detectó como error. En fin, casi toda la formatación de la pantalla es hecha por este comando. Unos pocos atributos del comando =tput= pueden eventualmente no funcionar, esto en el caso de que el modelo de terminal definido por la variable $TERM, no tenga esta posibilidad incorporada. En la tabla siguiente, se presentan los principales atributos del comando y los efectos ejecutados sobre la pantalla, pero debes saber que existen muchos más que esos, mira sino: %TERMINAL_INI% $ tput it%OUT_INI% 8%OUT_FIM% %TERMINAL_FIM% Este ejemplo devolvió el tamaño inicial del <kbd><TAB></kbd> ( <kbd>I</kbd>nitial <kbd>T</kbd> ab), y dime una cosa: para que quiero saber eso? Si quieres saber todo sobre el comando tput (y mira que es de nunca acabar), vea a: http://www.cs.utah.edu/dept/old/texinfo/tput/tput.html#SEC4. <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Principales Opciones del Comando tput* || | <b>Opciones de =tput= </b> | *Efecto* | | =cup lin col= | <kbd>CU</kbd>rsor <kbd>P</kbd>osition - Posiciona el cursor en la línea lin y columna col. El origen es cero | | =bold= | Coloca la pantalla en modo de realce | | =rev= | Coloca la pantalla en modo de vídeo inverso | | =smso= | Idéntico al anterior | | =smul= | A partir de esta instrucción, los caracteres tecleados aparecerán sublineados en la pantalla | | =blink= | Los caracteres tecleados aparecerán intermitentes | | =sgr0= | Después de usar uno de los atributos de arriba, se usa este para restaurar la pantalla a su modo normal | | =reset= | Limpia la pantalla y restaura sus definiciones de acuerdo con el =terminfo= o sea, la pantalla vuelve al patrón definido por la variable =$TERM= | | =lines= | Devuelve la cantidad de líneas de la pantalla en el momento de la instrucción | | =cols= | Devuelve la cantidad de columnas de la pantalla en el momento de la instrucción | | =el= | <kbd>E</kbd>rase <kbd>L</kbd>ine - Borra la línea a partir de la posición del cursor | | =ed= | <kbd>E</kbd>rase <kbd>D</kbd>isplay - Borra la pantalla a partir de la posición del cursor | | =il n= | <kbd>I</kbd>nsert <kbd>L</kbd>ines - Introduce =n= líneas a partir de la posición del cursor | | =dl n= | <kbd>D</kbd>elete <kbd>L</kbd>ines - Borra =n= líneas a partir de la posición del cursor | | =ech n= | <kbd>E</kbd>rase <kbd>CH</kbd>aracters - Borra =n= caracteres a partir de la posición del cursor | | =sc= | <kbd>S</kbd>ave <kbd>C</kbd>ursor position - Graba la posición del cursor | | =rc= | <kbd>R</kbd>estore <kbd>C</kbd>ursor position - Coloca el cursor en la posición marcada por el último =sc= | </center> Vamos a hacer un programa bien sencillo para mostrar algunos atributos de este comando. Es el famoso usado y abusado Hola Mundo, sólo que esta frase será escrita en el centro de la pantalla y en vídeo inverso y después de eso, el cursor volverá hasta la posición en que estaba antes de escribir esta frase tan creativa. Observa: %TERMINAL_INI% $ cat hola.sh%OUT_INI% #!/bin/bash # Script bobo para testar # el comando tput (versión 1) Columnas=`tput cols` # Grabando cantidad columnas Líneas=`tput lines` # Grabando cantidad líneas Línea=$((Líneas / 2)) # Cual es la línea del medio de la pantalla? Columna=$(((Columnas - 11) / 2)) # Centrando el mensaje en la pantalla tput sc # Grabando posición del cursor tput cup $Línea $Columna # Posicionándose para escribir tput rev # Vídeo inverso echo Hola Mundo! tput sgr0 # Restaura el vídeo a normal tput rc # Restaura el cursor a la posición original%OUT_FIM% %TERMINAL_FIM% Como el programa ya está todo comentado, creo que la única explicación necesaria sería para la línea en que es creada la variable =Columna= y lo extraño allí es aquél número =11=, este numero es el tamaño de la cadena que pretendo escribir (Hola Mundo). De esta forma, este programa solamente conseguiría centrar cadenas de 11 caracteres, sin embargo, mira esto: %TERMINAL_INI% $ var=Conversa $ echo ${#var}%OUT_INI% 8%OUT_FIM% $ var="Conversa de Bar" $ echo ${#var}%OUT_INI% 15%OUT_FIM% %TERMINAL_FIM% Ahhh, mejoró! Entonces ahora sabemos que la construcción =${#variable}= devuelve la cantidad de caracteres de =variable=. De esta forma, vamos a optimizar nuestro programa para que escriba en vídeo inverso y en el centro de la pantalla, la cadena pasada como parámetro y que después el cursor vuelva a la posición en que estaba antes de la ejecución del script. %TERMINAL_INI% $ cat hola.sh%OUT_INI% #!/bin/bash # Script bobo para testar # el comando tput (versión 2) Columnas=`tput cols` # Grabando cantidad columnas Líneas=`tput lines` # Grabando cantidad líneas Línea=$((Líneas / 2)) # Cual es la línea del medio de la pantalla? Columna=$(((Columnas - ${#1}) / 2)) #Centrando el mensaje en la pantalla put sc # Grabando posición del cursor tput cup $Línea $Columna # Posicionándose para escribir tput rev # Vídeo inverso echo $1 tput sgr0 # Restaura vídeo a normal tput rc # Restaura cursor en la posición original%OUT_FIM% %TERMINAL_FIM% Este script es igual al anterior, sólo que cambiamos el valor fijo de la versión anterior (=9=), por =${#1}=, donde éste =1= es el =$1= o sea, esta construcción devuelve el tamaño del primer parámetro pasado para el programa. Si el parámetro que yo quisiese pasar tuviese espacios en blanco, tendría que colocarlo todo entre comillas, sino el =$1= sería solamente el primer pedazo. Para evitar este problema, es solo necesario substituir el =$1= por =$*=, que como sabemos es el conjunto de todos los parámetros. Entonces aquella línea quedaría así: <verbatim> Columna=`$(((Columnas - ${#*}) / 2))` #Centrando el mensaje en la pantalla </verbatim> y la línea =echo $1= pasaría a ser =echo $*=. Pero no te olvides de que cuando lo ejecutes, tienes que pasar la frase que deseas centrar como un parámetro. ---++ Y ahora podemos leer los dados de la pantalla Bien, a partir de ahora vamos a aprender todo sobre lectura, solo que no te puedo enseñar a leer las cartas o el futuro, porque sino ya seria rico, estaria en un _pub_ de Londres, tomando _scotch_ y no en un bar tomando "chopp". Pero vamos a continuar. La última vez que nos encontramos aquí ya te dí una introducción sobre el comando =read=. Para comenzar su análisis más detallada. fíjate en esto: %TERMINAL_INI% $ read var1 var2 var3%OUT_INI% Conversa de Bar%OUT_FIM% $ echo $var1%OUT_INI% Conversa%OUT_FIM% $ echo $var2%OUT_INI% de%OUT_FIM% $ echo $var3%OUT_INI% Bar%OUT_FIM% $ read var1 var2%OUT_INI% Conversa de Bar%OUT_FIM% $ echo $var1%OUT_INI% Conversa%OUT_FIM% $ echo $var2%OUT_INI% de Bar%OUT_FIM% %TERMINAL_FIM% Como viste, el =read= recibe una lista separada por espacios en blanco y coloca cada ítem de esta lista en una variable. Si la cantidad de variables es menor que la cantidad de ítems, la última variable recibe el resto de los parámetros. Yo mencioné una lista separada por espacios en blanco? Pero ahora que ya lo conoces todo sobre el =$IFS= (<kbd>I</kbd>nter <kbd>F</kbd>ield <kbd>S</kbd>eparator) que te presenté cuando hablamos del comando =for=, todavía crees eso? Vamos a verificarlo directamente en el _prompt_: %TERMINAL_INI% $ oIFS="$IFS" $ IFS=: $ read var1 var2 var3%OUT_INI% Conversa de Bar%OUT_FIM% $ echo $var1%OUT_INI% Conversa de Bar%OUT_FIM% $ echo $var2 $ echo $var3 $ read var1 var2 var3%OUT_INI% Conversa:de:Bar%OUT_FIM% $ echo $var1%OUT_INI% Conversa%OUT_FIM% $ echo $var2%OUT_INI% de%OUT_FIM% $ echo $var3%OUT_INI% Bar%OUT_FIM% $ IFS="$oIFS" %TERMINAL_FIM% Te diste cuenta, estaba equivocado! La verdad es que el =read= lee una lista, así como el =for=, separada por los caracteres de la variable =$IFS=. Fíjate entonces como esto puede facilitarte la vida: %TERMINAL_INI% $ grep julio /etc/passwd%OUT_INI% julio:x:500:544:Julio C. Neves - 7070:/home/julio:/bin/bash%OUT_FIM% $ oIFS="$IFS" # Grabando IFS $ IFS=: $ grep julio /etc/passwd | read lname lixo uid gid coment home shell $ echo -e "$lname\n$uid\n$gid\n$coment\n$home\n$shell"%OUT_INI% julio 500 544 Julio C. Neves - 7070 /home/julio /bin/bash%OUT_FIM% $ IFS="$oIFS" # Restaurando IFS %TERMINAL_FIM% Como viste, la salda del =grep= fue redireccionada hacia el comando =read= que leyó todos los campos de una sola vez. La opción =-e= del =echo= fue usada para que el =\n= fuera entendido como un salto de línea (_new line_), y no como un literal. En el Bash existen diversas opciones del =read= que sirven para facilitarte la vida. Observa la siguiente tabla: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Opciones del comando read en Bash* || | *Opción* | *Acción* | | =-p prompt= | Escribe el =prompt= antes de hacer la lectura | | =-n num= | Lee hasta =num= caracteres | | =-t seg= | Espera =seg= segundos para que concluya la lectura | | =-s= | Lo que está siendo tecleado no aparece en la pantalla | </center> Y ahora directo a los ejemplos cortos para demostrar estas opciones. Para leer un campo "Matrícula": %TERMINAL_INI% $ echo -n "Matricula: "; read Mat # -n no salta línea%OUT_INI% Matricula: 12345%OUT_FIM% $ echo $Mat%OUT_INI% 12345%OUT_FIM% %TERMINAL_FIM% O simplificando con la opción =-p=: %TERMINAL_INI% $ read -p "Matricula: " Mat%OUT_INI% Matricula: 12345%OUT_FIM% $ echo $Mat%OUT_INI% 12345%OUT_FIM% %TERMINAL_FIM% Para leer una determinada cantidad de caracteres: %TERMINAL_INI% $ read -n5 -p"CEP: " Num ; read -n3 -p- Compl%OUT_INI% CEP: 12345-678%OUT_FIM%$ $ echo $Num%OUT_INI% 12345%OUT_FIM% $ echo $Compl%OUT_INI% 678%OUT_FIM% %TERMINAL_FIM% En este ejemplo hicimos dos =read=: uno para la primera parte del CEP y otra para su complemento y de este modo formateamos la entrada de datos. El signo de pesos (=$=) después del último número tecleado, es porque el =read= no tiene el _new-line_ implicito por _default_ como lo tiene el =echo=. Para leer hasta que un determinado tiempo termine (conocido como _time out_): %TERMINAL_INI% $ read -t2 -p "Digite su nombre completo: " Nom || echo 'Ah perezoso!'%OUT_INI% Escriba su nombre completo: JAh perezoso!%OUT_FIM% $ echo $Nom $ %TERMINAL_FIM% Obviamente esto fue una broma, ya que solo tenía 3 segundos para escribir mi nombre completo y sólo me dio tiempo de teclear una =J= (aquella pegada al =Ah=), pero me sirvió para mostrar dos cosas: 1. El comando después del par de barras verticales (=||=) (el o lógico, te acuerdas?) será ejecutado en el caso que la escritura no haya terminado en el tiempo estipulado; 1. La variable =Nom= permaneció vacía. Esta tendrá valores solamente cuando el =<ENTER>= sea tecleado. Para leer un dato sin ser mostrado en la pantalla: %TERMINAL_INI% $ read -sp "Seña: "%OUT_INI% Seña: %OUT_FIM%$ echo $REPLY%OUT_INI% secreto :)%OUT_FIM% %TERMINAL_FIM% Aprovecho un error para mostrarte un detalle de programación. Cuando escribi la primera línea, me olvidé de colocar el nombre de la variable que iría a recibir la contraseña, y sólo noté eso cuando fui a listar su valor. Por suerte la variable =$REPLY= del Bash, posee la última cadena leída y me aproveché de esto para no perder el viaje. Verifica tu mismo lo que acabo de hacer. Pero el ejemplo que dí, era para mostrar que la opción =-s= impide que lo que está siendo tecleado se vea en la pantalla. Como en el ejemplo anterior, la falta del _new-line_ hizo con que el _prompt_ del comando (=$=) permaneciese en la misma línea. Bien, ahora que sabemos leer de la pantalla, veamos como se leen los datos de los archivos. ---+++ Vamos a leer archivos? Como ya te habia dicho y te debes de acordar, el =while= verifica un comando y ejecuta un bloque de instrucciones mientras este comando de una respuesta correcta. Cuando estás leyendo un archivo que te dá permiso de lectura, el =read= sólo dará una respuesta errónea cuando alcance el =EOF= (_end of file_), de esta forma podemos leer un archivo de dos maneras: 1 - Redireccionando la entrada del archivo hacia el bloque del =while= así: <verbatim> while read Línea do echo $Línea done < archivo </verbatim> 2 - Redireccionando la salida de un =cat= hacia el =while=, de la siguiente forma: <verbatim> cat archivo | while read Línea do echo $Línea done </verbatim> Cada uno de los procesos tiene sus ventajas y desventajas: Ventajas del primer proceso: * Es más rápido; * No necesita de un _subshell_ para asistirlo; Desventaja del primer proceso: * en un bloque de instrucciones grande, el redireccionamento queda poco visible, lo que a veces perjudica la visualización del código; Ventaja del segundo proceso: * Como el nombre del archivo está antes del =while=, es más fácil la visualización del código. Desventajas del segundo proceso: * El _Pipe_ (=|=) llama un _subshell_ para interpretarlo, volviendo el proceso más lento, pesado y a veces problemático (mira los ejemplos que siguen). %TERMINAL_INI% $ cat readpipe.sh%OUT_INI% #!/bin/bash # readpipe.sh # Ejemplo de read pasando archivo por pipe. Ultimo="(vacío)" cat $0 | # Pasando el arch. del script ($0) p/ while while read Línea do Ultimo="$Línea" echo "-$Ultimo-" done echo "Acabó, Último=:$Ultimo:"%OUT_FIM% %TERMINAL_FIM% Vamos a ver su ejecución: %TERMINAL_INI% $ readpipe.sh%OUT_INI% -#!/bin/bash- -# readpipe.sh- -# Ejemplo de read pasando archivo por pipe.- -- -Ultimo="(vacío)"- -cat $0 | # Pasando el arch. del script ($0) p/ while- -while read Línea- -do- -Ultimo="$Línea"- -echo "-$Ultimo-"- -done- -echo "Acabó, Último=:$Ultimo:"- Acabó, Último=:(vacío):%OUT_FIM% %TERMINAL_FIM% Como viste, el _script_ lista todas sus própias líneas con un signo de menos (=-=) antes y otro después y al final muestra el contenido de la variable =$Ultimo=. Sin embargo, observa que el contenido de esta variable permanece como =(vacío)=. - Será que la variable no fue actualizada? - Lo fue, y eso puede ser comprobado porque la línea =echo "-$Ultimo-"= lista correctamente las líneas. - Entonces que paso? - Pues que como ya te dije, el bloque de instrucciones redireccionado por el _pipe_ (=|=) es ejecutado en un _subshell_ y allí las variables son actualizadas. Cuando este _subshell_ termina, las actualizaciones de las variables se van junto con él, para los quintos infiernos. Observa que voy a hacer un pequeño cambio pasando el archivo por redireccionamento de entrada (<) y así las cosas pasarán a funcionar de una forma más perfecta: %TERMINAL_INI% $ cat redirread.sh%OUT_INI% #!/bin/bash # redirread.sh # Ejemplo de read pasando archivo por redireccionamento de entrada (<). Ultimo="(vacío)" while read Línea do Ultimo="$Línea" echo "-$Ultimo-" done < $0 # Pasando el arch. del script ($0) p/ while echo "Acabó, Último=:$Ultimo:"%OUT_FIM% %TERMINAL_FIM% Y mira su ejecución sin errores: %TERMINAL_INI% $ redirread.sh%OUT_INI% -#!/bin/bash- -# redirread.sh- -# Ejemplo de read pasando archivo por redireccionamento de entrada (<).- -- -Ultimo="(vacío)"- -while read Línea- -do- -Ultimo="$Línea"- -echo "-$Ultimo-"- -done < $0 # Pasando el arch. del script ($0) p/ while- -echo "Acabó, Último=:$Ultimo:"- Acabó, Último=:echo "Acabó, Último=:$Ultimo:":%OUT_FIM% %TERMINAL_FIM% Bien amigos de la Red _Shell_, para finalizar el comando =read= sólo falta un pequeño e importante detalle que voy a mostrar utilizando un ejemplo práctico. Imagina que quieres listar en pantalla un archivo y que cada diez registros esta lista se detenga para que el operador pueda leer el contenido de la pantalla y sólo volverá a funcionar (_scroll_) después que el operador pulse cualquier tecla. Para no gastar absurdamente papel (de la Linux Magazine), voy a hacer esta lista en la horizontal y mi archivo (=numeros=), que tiene 30 registros solamente con números secuenciales. Mira: %TERMINAL_INI% $ seq 30 > numeros $ cat 10porpag.sh%OUT_INI% #!/bin/bash # Prg de test para escribir # 10 líneas y parar para leer # Versión 1 while read Num do let <nop>ContLin++ # Contando... echo -n "$Num " # -n para no saltar línea ((<nop>ContLin % 10)) > /dev/null || read done < numeros%OUT_FIM% %TERMINAL_FIM% Como forma de hacer un programa genérico creamos la variable =$ContLin= (por que en la vida real, los registros no son solamente números secuenciales) y pararemos para leer cuando el resto de la división por =10= sea cero (mandando la salida para =/dev/null= de forma de que no aparezca en la pantalla, ensuciandola). Sin embargo, cuando fui a ejecutarlo me dio el siguiente error: %TERMINAL_INI% $ 10porpag.sh%OUT_INI% 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 23 24 25 26 27 28 29 30%OUT_FIM% %TERMINAL_FIM% Fíjate que falta el número =11= y que la lista no se paro en el =read=. Lo que paso es que la entrada del _loop_ estaba redireccionada desde el archivo =numeros= y de esta forma, la lectura fue hecha encima de este archivo, así perdimos el =11= (y tambiém el =22=). Vamos a mostrar entonces como debería quedar para funcionar correctamente: %TERMINAL_INI% $ cat 10porpag.sh%OUT_INI% #!/bin/bash # Prg de test para escribir # 10 líneas y parar para leer # Versión 2 while read Num do let <nop>ContLin++ # Contando... echo -n "$Num " # -n para no saltar línea ((<nop>ContLin % 10)) > /dev/null || read < /dev/tty done < numeros%OUT_FIM% %TERMINAL_FIM% Observa que ahora la entrada del =read= fue redireccionada desde =/dev/tty=, que no es nada más que el terminal corriente, forzando de esta forma que la lectura sera hecha del teclado y no de números. Es bueno resaltar que esto no sucede solamente cuando usamos el redireccionamento de entrada, se hubieramos usado el redireccionamento via _pipe_ (=|=), habría pasado lo mismo. Observa ahora su ejecución: %TERMINAL_INI% $ 10porpag.sh%OUT_INI% 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30%OUT_FIM% %TERMINAL_FIM% Esto está casi bien, pero falta un poco para quedar excelente. Vamos a mejorar un poco el ejemplo para que lo reproduzcas y verifiques (pero antes de verificar, aumenta el número de registros de =numeros= o reduce el tamaño de la pantalla, para que haya un salto de página). %TERMINAL_INI% $ cat 10porpag.sh%OUT_INI% #!/bin/bash # Prg de test para escribir # 10 líneas y parar para leer # Versión 3 clear while read Num do ((<nop>ContLin++)) # Contando... echo "$Num" ((<nop>ContLin % (`tput lines` - 3))) || { read -n1 -p"Teclee Algo " < /dev/tty # para leer cualquier caracter clear # limpia la pantalla despues de la lectura } done < numeros%OUT_FIM% %TERMINAL_FIM% El cambio principal hecho en este ejemplo, es con relación al salto de página, ya que esta hecho en cada cantidad-de-líneas-de-pantalla (=tput lines=) menos (=-=) =3=, o sea, si la pantalla tiene 25 líneas, listará 22 registros y parará para su lectura. En el comando =read= también fue hecha una alteración, incluyendo un =-n1= para leer solamente un caracter sin ser necesariamente un =<ENTER>= y la opción =-p= para dar el mensaje. - Bien amigo mio, por hoy ya basta porque me parece que estás saturado de esto... - No, no lo estoy, realmente puede continuar... - Si tu no lo estás, yo sí... Pero ya que estás tan entusiasmado con el _Shell_, te voy a dejar un ejercicio de aprendizaje que mejorara tu CDteca y que es bastante simple. Reescribe tu programa que registra CDs para montar toda la pantalla con un único =echo= y que después vaya posicionandose frente a cada campo para recibir los valores que serán tecleados por el operador. Y no te olvides, cualquer duda o falta de compañia para tomar una cerveza o hasta para hablar mal de los políticos lo único que tienes que hacer es mandarme un e-mail para <a href="mailto:julio.neves@gmail.com?Subject=Dudas Conversas de bar botequim">julio.neves@gmail.com</a>. Voy aprovechar también para mandar mi aviso publicitario: puedes decirle a los amigos que quien quiera hacer un curso nota diez de programación en _Shell_ que mande un e-mail para <a href="mailto:julio.neves@uniriotec.br?Subject=Curso de Shell con Julio Neves">julio.neves@uniriotec.br</a> para informarse. Gracias y hasta la <a href="https://twiki.softwarelivre.org/bin/view/TWikiBar/TWikiBarConversa008">próxima</a> -- Main.HumbertoPina - 17 Jan 2007
E
dit
|
A
ttach
|
P
rint version
|
H
istory
: r9
<
r8
<
r7
<
r6
<
r5
|
B
acklinks
|
V
iew topic
|
M
ore topic actions
Topic revision: r9 - 06 Feb 2008 - 00:30:52 -
CollonsTorre
TWikiBar
Página Inicial
Últimas alterações
Índice
Procurar
Estatísticas de Uso
Aviso de Atualização
Configurações Gerais
Projeto Gráfico
Mapa do Site
Quem Somos
Registre-se
?
Regras de Formatação
Biblioteca Gráfica
?
Carinhas Gráficas
Webs Wiki-SL
Amadeu
Anapolivre
ArquivoLivre
Arte
BahiaSocial
BeaBa
BibliotecaLivre
Blogs
BrasilDigital
BrasilELivre
BSM
Ccsa
CESL
CoberturaWiki
Cooperativas
Curriculo
DarvinMarosin
DiaD
Dinamicoop
Economia
EconomiaSolidaria
EducacaoLivre
Ekaaty
Emacsbr
ENSL
Fatos
Festival3
Festival4
Flisol
Fmpb
Formatos
Foswikibr
FSM2005
GNOMEBR
GTTemario2004
GTWeb
Guialivre
HDC
Incubus
InkscapeBrasil
Jogos
KdeBR
KSP
LGM
LinuxStokDoc
Livros
Main
Mentores
MHHOB
MinuanoDigital
MoradiaECidadania
OlhosDagua
Olimpo
OLPC
OOPTQ
Papers
PCLivre
PentahoBrasil
Pessoas
Portal
Prefeituras
PSLAL
PSLBA
PSLBancarios
PSLBrasil
PSLGO
PSLMA
PSLMG
PSLMIP
PSLMT
PSLMulheres
PSLPI
PubFisl10
PubFisl7
PubFisl8
PubFisl9
QuilomboDoSopapo
RadioSL
RedeMesh
RedePopular
RobotWars
Sandbox
Saudelivre
Scribus
Sementes
Shakya
SLRJ
SoftwareLivreIrece
SoftwareLivreVS
SoLiSC
SuporteLivre
System
Telecentros
TeseSA
TextoLivre
TV
TWikiBar
TWikiPtbr
UNELivre
UNIMIX
VilaTorres
WebNordeste
WTRD2004
Este Menu
?skin=free
English
Español
Português brasileiro
Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-SL?
Send feedback