You are here:
Wiki-SL
>
TWikiBar Web
>
TWikiBarConversa004
(04 Feb 2008,
CollonsTorre
)
(raw view)
E
dit
A
ttach
---+ Conversación de bar IV ------ %TOC% - Y entonces amigo mio, intentaste hacer el ejercicio que te pedí para reforzar tus conocimientos? - Claro, que si! En programación, si no se practica, no se aprende. Me pediste que hiciera un _scriptisiño_ para informar si un determinado usuario, que será pasado como parámetro, esta logado (ajjjj!) o no. Hice lo siguiente: %TERMINAL_INI% $ cat logado%OUT_INI% #!/bin/bash # Busca si una persona está logada o no if who | grep $1 then echo $1 está logado else echo $1 no se encuentra en la vecindad fi%OUT_FIM% %TERMINAL_FIM% - Calma amigo! Ya vi que hoy llegaste lleno de deseos de trabajar, primero vamos a pedir nuestros "choppes" de costumbre y después vamos al _Shell_. Chico!, tráeme dos "choppes", uno sin espuma! - Ahora que ya mojamos nuestros labios, vamos a echar un vistazo a la ejecución de tu programa: %TERMINAL_INI% $ logado jneves%OUT_INI% jneves pts/0 Oct 18 12:02 (10.2.4.144) jneves está logado%OUT_FIM% %TERMINAL_FIM% Realmente funcionó. Pasé mi _login_ como parámetro y él me informó que estaba logado, sin embargo, al mismo tiempo salió una línea que no pedí. Esta línea es la salida del comando =who=, y para evitar que eso pase, lo único que hay que hacer es mandarla hacia el agujero negro que a estas altura ya sabes que es el =/dev/null=. Veamos entonces como quedaría: %TERMINAL_INI% $ cat logado%OUT_INI% #!/bin/bash # Busca si una persona está logada o no (versión 2) if who | grep $1 > /dev/null then echo $1 está logado else echo $1 no se encuentra en la vecindad fi%OUT_FIM% %TERMINAL_FIM% Ahora vamos a los tests: %TERMINAL_INI% $ logado jneves%OUT_INI% jneves está logado $ logado chico chico no se encuentra en la vecindad%OUT_FIM% %TERMINAL_FIM% %ATENCION_INI% Ah, ahora si! Acuérdate de esto: la mayor parte de los comandos tienen una salida patrón y una salida de errores (el =grep= es una de las pocas excepciones, ya que no da mensajes de error cuando no encuentra una cadena) y es necesario estar muy atentos para redirecionarlas hacia el agujero negro cuando sea necesario. %ATENCION_FIM% Bueno, ahora vamos a cambiar de asunto: la última vez que nos encontramos aquí en el Bar, te estaba mostrando los comandos condicionales y cuando ya estábamos con la garganta seca hablando sobre el if, me preguntaste como se verifican condiciones. Veamos entonces ---++ El Comando test Bien, todos estamos acostumbrados a usar el =if= para verificar condiciones, y estas condiciones siempre son: mayor, menor, mayor o igual, menor o igual, igual y diferente. En _Shell_ para verificar condiciones, usamos el comando =test=, sólo que este es mucho más poderoso de lo que estamos habituados. Primero te voy a mostrar las principales opciones (existen muchas otras), para verificar la existencia de archivos en el disco: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Opciones del Comando test para archivos* || | *Opción* | *Verdadero si:* | | =-e arch= | =arch= existe | | =-s arch= | =arch= existe y tiene tamaño mayor que cero | | =-f arch= | =arch= existe y es un archivo regular | | =-d arch= | =arch= existe y es un directorio; | | =-r arch= | =arch= existe y con derechos de lectura | | =-w arch= | =arch= existe y con derechos de escritura | | =-x arch= | =arch= existe y con derechos de ejecución | </center> Observa ahora las principales opciones para verificar cadenas de caracteres: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Opciones del comando =test= para cadenas de caracteres* || | *Opción* | *Verdadero si:* | | =-z cadena= | Tamaño de =cadena= es cero | | =-n cadena= | Tamaño de =cadena= es mayor que cero | | =cadena= | La cadena =cadena= tiene tamaño mayor que cero | | =c1 = c2= | Cadena =c1= y =c2= son idénticas | </center> Y crees que se acabó ahí? Pues estás engañado! Ahora viene la parte a la que estás más acostumbrado, o sea las famosas comparaciones con números. Fijate en la tabla que sigue: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Opciones del comando =test= para números* ||| | *Opción* | *Verdadero si:* | *Significado* | | =n1 -eq n2= | =n1= y =n2= son iguales | equal | | =n1 -ne n2= | =n1= y =n2= no son iguales | not equal | | =n1 -gt n2= | =n1= es mayor que =n2= | greater than | | =n1 -ge n2= | =n1= es mayor o igual a =n2= | greater or equal | | =n1 -lt n2= | =n1= es menor que =n2= | less than | | =n1 -le n2= | =n1= es menor o igual a =n2= | less or equal | </center> Además de todo eso, se suman a las opciones que te mostré las siguientes opciones: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Operadores* || | *Operador* | *Finalidad* | | Paréntesis =( )= | Agrupar | | Admiración =!= | Negar | | =-a= | =Y= lógico | | =-o= | =O= lógico | </center> Ufa! Como viste hay mucha cosa y como te dije al comienzo, nuestro =if= es mucho más poderoso que los de otros. Vamos a ver en unos ejemplos como funciona todo esto, primero verificaremos la existencia de un directorio: Ejemplos: <verbatim> if test -d lmb then cd lmb else mkdir lmb cd lmb fi </verbatim> En este ejemplo, verifiqué la existencia de un directorio definido =lmb=, en caso negativo (=else=), éste seria creado. Ya sé, vas a criticar mi razonamiento diciendo que el _script_ no está optimizado. Lo sé perfectamente, pero quería que entendieras este ejemplo, para poder usar después el signo de admiración (=!=) como un negador del =test=. Mira esto: <verbatim> if test ! -d lmb then mkdir lmb fi cd lmb </verbatim> De esta forma el directorio =lmb= sería creado solamente si este no existiese, y esta negación se debe al signo de admiración (=!=) que precede a la opción =-d=. Al finalizar la ejecución de este fragmento de _script_, el programa estaría seguramente dentro del directorio =lmb=. Vamos a ver dos ejemplos para entender como se diferencia la comparación entre números y entre cadenas. <verbatim> cad1=1 cad2=01 if test $cad1 = $cad2 then echo Las variables son iguales. else echo Las variables son diferentes. fi </verbatim> Ejecutando el fragmento del programa arriba, resulta: =Las variables son diferentes.= Vamos a modificarlo un poco, de manera que la comparación esta vez sea numérica: <verbatim> cad1=1 cad2=01 if test $cad1 -eq $cad2 then echo Las variables son iguales. else echo Las variables son diferentes. fi </verbatim> Y lo ejecutamos nuevamente: =Las variables son iguales.= Como viste, en las dos ejecuciones obtuve resultados diferentes porque la cadena =01= es realmente diferente de la cadena =1=, sin embargo, la cosa cambia cuando las variables son verificadas en forma numérica, ya que el número =1= es igual al número =01=. Ejemplos: Para mostrar el uso de los conectores =-o= (=O=) y =-a= (=Y=), tengo un ejemplo bien grosero, hecho directamente en el _prompt_ (pido disculpas a los zoólogos, ya que no entendiendo nada de reino, clase, orden, familia, género y especie, puede que lo que estoy llamando familia o género tenga grandes posibilidades de ser incorrecto): %TERMINAL_INI% $ Familia=felina $ Genero=gato $ if test $Familia = canina -a $Genero = lobo -o $Familia = felina -a $Genero = leon > then > echo Cuidado > else > echo Se puede acariciar > fi%OUT_INI% Se puede acariciar%OUT_FIM% %TERMINAL_FIM% En este ejemplo en caso de que el animal fuera de la familia canina =Y= (=-a=) del género lobo, =O= (=-o=) de la familia felina =Y= (=-a=) del género leon, se daria un aviso de alerta, en caso contrario el mensaje sería de incentivo. %DICA_INI% Los signos de mayor (=>=) al inicio de las líneas internas al =if= son los _prompts_ de continuación (que están definidos en la variable =$PS2=) y cuando el _Shell_ identifica que un comando continuará en la línea siguiente, automáticamente los va colocado, hasta que el comando sea finalizado. %DICA_FIM% Vamos a cambiar el ejemplo para ver si continúa funcionando: %TERMINAL_INI% $ Familia=felino $ Genero=gato $ if test $Familia = felino -o $Familia = canino -a $Genero = onza -o $Genero = lobo > then > echo Cuidado! > else > echo Puede acariciar > fi%OUT_INI% Cuidado!%OUT_FIM% %TERMINAL_FIM% Obviamente la operación resultó en error, ya que la opción =-a= tiene prioridad sobre la =-o=, y así lo que se evaluó primero, fué la expresión: =$Familia = canino -a $Genero = onza= Que fué evaluada como falsa, y dió el seguiente resultado: =$Familia = felino -o FALSO -o $Genero = lobo= Que una vez resuelta dió: =VERDADERO -o FALSO -o FALSO= Como ahora todos los conectores son =-o=, y para que una serie de expresiones conectadas entre sí por diversos =O= lógicos sea verdadera, basta que una de ellas lo sea, la expresión final resultó como =VERDADERO= y el =then= fue ejecutado de forma incorrecta. Para que vuelva a funcionar hagamos lo seguiente: %TERMINAL_INI% $ if test \($Familia = felino -o $Familia = canino\) -a \($Genero = onza -o $Genero = lobo\) > then > echo Cuidado! > else > echo Puede acariciar > fi%OUT_INI% Puede acariciar%OUT_FIM% %TERMINAL_FIM% De esta forma, con el uso de los paréntesis agrupamos las expresiones con el conector =-o=, dando prioridad a sus ejecuciones y resultando: =VERDADERO -a FALSO= Para que sea =VERDADERO= el resultado de dos expresiones ligadas por el conector =-a= es necesario que ambas sean verdaderas, lo que no es el caso del ejemplo arriba citado. Así el resultado final fue =FALSO=, siendo entonces el =else= correctamente ejecutado. Si quisieramos escojer un CD que tenga músicas de 2 artistas diferentes, nos sentimos tentados a usar un =if= con el conector =-a=, pero siempre es bueno recordar que el _bash_ nos dá muchos recursos y eso podría ser hecho de forma mucho más simple con un único comando =grep=, de la siguiente manera: %TERMINAL_INI% $ grep Artista1 musicas | grep Artista2 %TERMINAL_FIM% De la misma forma, para escojer CDs que tengan la participación del =Artista1= y del =Artista2=, no es necesario montar un =if= con el conector =-o=. El =egrep= (o =grep -E=, siendo éste más recomendable), también nos resuelve eso. Fijate como: %TERMINAL_INI% $ egrep (Artista1|Artista2) musicas %TERMINAL_FIM% O (en ese caso específico) el propio =grep= puro y simple podría ayudarnos: %TERMINAL_INI% $ grep Artista[12] musicas %TERMINAL_FIM% En el =egrep= arriba, fue usada una expresión regular, donde la barra vertical (=|=) trabaja como un =O= lógico y los paréntesis son usados para limitar la amplitud de éste =O=.Ya en el =grep= de la línea siguiente, la palabra =Artista= debe ser seguida por alguno de los valores de la lista formada por los paréntesis rectos (=[ ]=), o sea, =1= o =2=. - Está bien, acepto el argumento, el =if= del _Shell_ es mucho más poderoso que los otros conocidos, pero entre nosotros, esa construción del =if test ...= es muy extraña, y poco legible. - Si, tienes toda la razón, tampoco me es simpática y me parece que a nadie le gusta. Creo que fue por eso, que el _Shell_ incorporó otra sintáxis que substituye el comando =test=. Ejemplos: Para esto vamos a ver nuevamente aquél ejemplo para cambiar de directorios, que era así: <verbatim> if test ! -d lmb then mkdir lmb fi cd lmb </verbatim> y utilizando la nueva sintáxis, vamos a hacerla así: <verbatim> if [ ! -d lmb ] then mkdir lmb fi cd lmb </verbatim> O sea, el comando =test= puede ser substituído por un par de paréntesis rectos (=[ ]=), separados por espacios en blanco de los argumentos, lo que aumentará enormemente la legibilidad, pues el comando =if= quedara con una sintáxis parecida a de otras lenguajes y por este motivo, usaré el comando =test= de esta forma de ahora en adelante. ---++Querida, Encojieron el Comando Condicional! Si creees que se acabó, estás muy equivocado. Repara en la tabla (booleana) siguiente: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Valores Booleanos* | *Y* | *O* | | VERDADERO-VERDADERO | VERDADERO | VERDADERO | | VERDADERO-FALSO | FALSO | VERDADERO | | FALSO-VERDADERO | FALSO | VERDADERO | | FALSO-FALSO | FALSO | FALSO | </center> O sea, cuando el conector es =Y= y la primera condición es verdadera, el resultado final puede ser =VERDADERO= o =FALSO=, dependiendo de la segunda condición, ya en el conector =O=, en caso que la primera condición sea verdadera, el resultado siempre será =VERDADERO= y si la primera fuera falsa, el resultado dependerá de la segunda condición. Bueno, las personas que crearon el interpretador no son bobas y están siempre intentando optimizar al máximo los algoritmos. Por tanto, en el caso del conector =Y=, la segunda condición no será evaluada, en el caso de que la primera sea falsa, ya que el resultado será siempre =FALSO=. Ya con el =O=, la segunda será ejecutada solamente en el caso de que la primera sea falsa. Aprovechando eso, crearon una forma abreviada de hacer tests. Bautizaron el conector =Y= de =&&= y el =O= de =||= y para ver como funciona esto, vamos a usarlos como test en nuestro viejo ejemplo de cambiar de directorio, que en su última versión estaba así: <verbatim> if [ ! -d lmb ] then mkdir lmb fi cd lmb </verbatim> Eso también podría ser escrito de la siguiente manera: <verbatim> [ ! -d lmb ] && mkdir lmb cd lmb </verbatim> O inclusive sacando la negación (=!=): <verbatim> [ -d lmb ] || mkdir lmb cd lmb </verbatim> En el primer caso, si el primer comando (el =test= que está representado por los paréntesis rectos) estuviera bien resultado, o sea, no existe el directorio =lmb=, el =mkdir= será ejecutado, porque la primera condición era verdadera y el conector era =Y=. En el ejemplo siguiente, verificaremos si el directorio =lmb= existe (en el anterior verificabamos si no existía) y en caso de que eso fuera verdadero, el =mkdir= no sería ejecutado porque el conector era =O=. Otra forma: =cd lmb || mkdir lmb= En este caso, si el =cd= diera error, sería creado el directorio =lmb= pero no sería ejecutado el =cd= hacia dentro de él. Para ejecutar más de un comando de esta forma, es necesario que hagamos un agrupamiento de comandos, eso se consigue con el uso de llaves (={ }=). Mira como sería la forma correcta: <verbatim> cd lmb || { mkdir lmb cd lmb } </verbatim> Todavia no está bien, porque en el caso de que el directorio no exista, el =cd= dará el mensaje de error correspondiente. Entonces debemos hacer: <verbatim> cd lmb 2> /dev/null || { mkdir lmb cd lmb } </verbatim> Como viste, el comando =if= nos permitió hacer un =cd= seguro de diversas maneras. Es siempre bueno recordar que el seguro a que me referí, es en lo referente al hecho de que al final de la ejecución, tu siempre estarás dentro de =lmb=, siempre que tengas permisos para entrar en =lmb=, permisos para crear un directorio en =../lmb=, haya espacio en el disco, ... ---++ Y toma test! Piensas que ya se acabó? Gran error! Todavia tenemos una forma de =test= más. Esta es muy buena porque te permite usar patrones para la comparación. Estos patrones atienden a las normas de Generación de Nombres de Archivos (_File Name Generation_, que son ligeramente parecidas con las Expresiones Regulares, pero no pueden ser confundidas con éstas). La diferencia de sintáxis de este para el =test= que acabamos de ver, es que este trabaja con dos parêntesis rectos de la siguiente forma: =[[ expresión ]]= Donde =expresión= es una de las que constan en la tabla siguiente: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Expresiones Condicionales Para Padrones* || | *Expresión* | *Retorna* | | =cadena == padrón= %BR% =cadena1 = padrón= | Verdadero si =cadena1= es igual a =padrón= | | =cadena1 != padrón= | Verdadero si =cadena1= no es igual a =padrón=. | | =cadena1 < cadena1= | Verdadero si =cadena1= está antes de =cadena1= alfabéticamente. | | =cadena1 > cadena1= | Verdadero si =cadena1= está después de =cadena1= alfabéticamente | | =expr1 && expr2= | "Y" lógico, Verdadero si ambos =expr1= y =expr2= son Verdaderos | | =expr1 ¦¦ expr2= | "O" lógico, Verdadero si =expr1= o =expr2= fueran Verdaderos | </center> %TERMINAL_INI% $ echo $H%OUT_INI% 13%OUT_FIM% $ [[ $H !== [0-9] || $H !== 1[0-2] ]] || echo Hora no válida%OUT_INI% Hora no válida%OUT_FIM% $H=12 $ [[ $H !== [0-9] || $H !== 1[0-2] ]] || echo Hora no válida $ %TERMINAL_FIM% En este ejemplo,verificamos si el contenido de la variable =$H= esta comprendido entre cero y nueve =([0-9])= o =(||)= si esta entre diez y doze =(1[0-2])=, dando un mensaje de error en caso que no sea asi. Ejemplos: Para saber si una variable tiene el tamaño de un y solamente un caracter, haz: %TERMINAL_INI% $ var=a $ [<nop>[ $var !== ? ]] && echo var tiene un caracter%OUT_INI% var tiene un caracter%OUT_FIM% $ var=aa $ [[ $var !== ? ]<nop>] && echo var tiene un caracter $ %TERMINAL_FIM% Como puedes imaginar, este uso de patrones para comparación, aumenta mucho el poderío del comando =test=. En el inicio de esta conversación, antes del último "choppe", afirmabamos que el comando =if= del interpretador _Shell_ es más poderoso que sus similares en otros lenguajes. Ahora que conocimos todo su espectro de funciones, dime: estas de acuerdo o no con esta afirmación? ---++Acaso Casa con case Veamos un ejemplo didáctico: dependiendo del valor de la variable =$opc= el _script_ deberá ejecutar una de las opciones: inclusión, exclusión, alteración o fin. Fijate como quedaría este fragmento de _script_: <verbatim> if [ $opc -eq 1 ] then inclusión elif [ $opc -eq 2 ] then exclusión elif [ $opc -eq 3 ] then alteración elif [ $opc -eq 4 ] then exit else echo Digite una opción entre 1 y 4 fi </verbatim> En este ejemplo viste el uso del =elif= con un =else if=, esta es una sintáxis válida y aceptada, pero podríamos hacerlo mejor y sería usando el comando =case=, que tiene la sintáxis siguiente: <verbatim> case $var in patrón1) cmd1 cmd2 cmdn ;; patrón2) cmd1 cmd2 cmdn ;; patrónn) cmd1 cmd2 cmdn ;; esac </verbatim> Donde la variable =$var= es comparada a los patrones =patrón1, ..., patrónn= y en el caso de que uno de ellos coincida, el bloque de comandos =cmd1, ..., cmdn= correspondiente será ejecutado hasta que encuentre un doble punto y coma (=;;=), en donde el flujo del programa se desviará hacia la instrucción inmediatamente siguiente, o sea el =esac=. En la formación de los patrones, son aceptados los siguientes caracteres: <center> %TABLE{ databg="#ffffff" headerrows="1" }% | *Caracteres Para Formacion de Padrones* || | *Caracter* | *Significado* | | =*= | Cualquier caracter ocurriendo cero o más veces | | =?= | Cualquier caracter ocurriendo una vez | | =[...]= | Lista de caracteres | | =¦= | =O= lógico | </center> Para mostrar como realmente queda mejor, vamos a repetir el ejemplo anterior, sólo que esta vez usaremos el =case= y no el =if ... elif ... else ... fi=. <verbatim> case $opc in 1) inclusión ;; 2) exclusión ;; 3) alteración ;; 4) exit ;; *) echo Digite una opción entre 1 y 4 esac </verbatim> Como debes haberte dado cuenta, usé el asterisco como la última opción, o sea, si el asterisco quiere decir cualquier cosa, entonces servirá para cualquier cosa que no este en el intervalo del 1 al 4. Otra cosa a tener en cuenta es que el doble punto y coma no es necesario antes del =esac=. Ejemplos: Vamos ahora a hacer un _script_ más radical. Te dará los buenos días, buenas tardes o buenas noches, dependiendo de la hora en que sea ejecutado, pero primero mira estos comandos: %TERMINAL_INI% $ date%OUT_INI% Tue Nov 9 19:37:30 BRST 2004%OUT_FIM% $ date +%H<nop>%OUT_INI% 19%OUT_FIM% %TERMINAL_FIM% El comando =date= informa de la fecha completa del sistema, sin embargo tiene diversas opciones para su enmascaramiento. En este comando, la formatación comienza con un signo de más (=+=) y los caracteres de formatación vienen después de un signo de porcentaje (=%=), así el =%H= significa la hora del sistema. Dicho esto, vamos al ejemplo: %TERMINAL_INI% $ cat bienvenido.sh%OUT_INI% #!/bin/bash # Programa bien educado que # da los Buenos dias, buenas tardes o # las buenas noches dependiendo de la hora Hora=$(date +%H) case $Hora in 0? | 1[01]) echo Buenos días ;; 1[2-7] ) echo Buenas tardes ;; * ) echo Buenas noches ;; esac exit%OUT_FIM% %TERMINAL_FIM% Fue pesado, verdad?. - Que vá!. Vamos a desmenuzar la resolución caso a caso (o sería case-a-case? :) ) =0? | 1[01]= - Significa cero seguido de cualquier cosa (=?=), o (=|=) uno seguido de cero o uno (=[01]=) o sea, esta línea pegó 01, 02, ... 09, 10 y 11; =1[2-7] = - Significa uno seguido de la lista de dos a siete, o sea, esta línea pegó 12, 13, ... 17; =* = - Significa todo aquello que no se encuadró en ninguno de los patrones anteriores. - Mira, hasta ahora hablé mucho y bebí poco. Ahora te voy a pasar un ejercicio para que lo hagas en tu casa y me des la respuesta la próxima vez que nos encontremos aqui en el bar, de acuerdo? - De acuerdo, pero antes informe a las personas que nos están acompañando en este curso, como pueden hacerlo para encontrarle, para hacerle críticas, hacer chistes, invitarle a una cerveza, un curso, unas charlas o hasta si quieren, para hablar mal de los políticos. - es fácil, mi e-mail es <a href="mailto:julio.neves@gmail.com?Subject=Dudas Conversas de Bar">julio.neves@gmail.com</a>, pero para de distraerme, que no me voy a olvidar de pasarte el _script_ de los deberes, y este es: quiero que hagas un programa que recibirá como parámetro el nombre de un archivo y que cuando sea ejecutado grabe este archivo con el nombre original seguido de una tilde (=~=), además colocaras este archivo dentro del =vi= (de paso, el mejor editor del cual se tiene noticia) para ser editado. Esto sirve para tener siempre la última copia buena del archivo en el caso de que la persona haga alteraciones indebidas. Obviamente, tendrás que hacer las investigaciones necesarias, como verificar si fué pasado un parámetro, si el archivo que fué pasado existe, ... En fin, lo que se te venga a la cabeza y tu creas que deba estar en el _script_. Entendiste? - Hum, hum... - Chico! Traeme otra más sin espuma, que aquí el amigo ya está pensando! :) Gracias y hasta la <a href="https://twiki.softwarelivre.org/bin/view/TWikiBar/TWikiBarConversa005">próxima</a> -- Main.HumbertoPina - 05 Oct 2006
E
dit
|
A
ttach
|
P
rint version
|
H
istory
: r12
<
r11
<
r10
<
r9
<
r8
|
B
acklinks
|
V
iew topic
|
M
ore topic actions
Topic revision: r12 - 04 Feb 2008 - 22:40:45 -
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