Conversación de Bar - Parte I
Diálogo escuchado entre un Linuxer y un empujador de mouse:
- Quién es el Bash?
- El Bash es el hijo mas nuevo de la familia Shell.
- Espera ahí! Quieres volverme loco? Tenía una duda y ahora me dejas con dos!
- No, loco ya lo eras antes de aparecer por aqui. Desde que decidiste usar aquél sistema operativo con el cual tienes que reiniciar tu máquina unas diez veces por dia y no tienes dominio ninguno sobre lo que está pasando en el computador. Pero deja eso de lado, te voy a explicar lo que es el Shell y los componentes de su familia y al final de la explicación me dirás: "Mi Dios del Shell! Porque no opté antes por Linux?".
El Ambiente Linux
Para que entiendas lo que es y como funciona el Shell, primero te mostraré como funciona el ambiente en capas de Linux. Da una mirada atenta en el gráfico que sigue:
En este gráfico se ve que la capa de hardware es la mas profunda estando formada por los componentes físicos de tu computador. Envolviendo a ésta, viene la capa del kernel que es el corazón de Linux, su núcleo, y es quien hace que el hardware funcione, efectuando su manejo y control. Los programas y comandos que envuelven el kernel, lo utilizan para realizar las tareas especificas para las cuales fueron desarrolladas. Encerrando todo eso viene el Shell que tiene este nombre porque en ingles, Shell significa concha, envoltura, o sea que, queda entre los usuarios y el sistema operativo, de forma que todo lo que interacciona con el sistema operativo, tiene que pasar por su filtro.
El Ambiente Shell
Bueno, si para llegar al núcleo de Linux, o sea al kernel que es lo que le interesa a cualquier aplicacion, es necesario el filtro del Shell, vamos entonces a entender como funciona este, y la forma de sacar el mayor provecho de las innúmerables facilidades que él nos ofrece.
El Linux por definición es un sistema multiusuario - no podemos nunca olvidar ésto – y para permitir el acesso de determinados usuarios e impedir la entrada de otros, existe un archivo llamado /etc/passwd que además de proveer datos para esta función, especie de "guardián de puerta" del Linux, también pasa información para el login de aquellos que consiguieron pasar por esta primera barrera. El último campo de sus registros, informa al sistema cual es el_Shell_ que la persona va a recibir cuando se "loguee" (Ajjjjj!!!).

Cuando dije que el último campo del /etc/passwd informa al sistema cual es el Shell que el usuario va a recibir al "loguearse", es para ser interpretado literalmente, o sea, si en este campo de su registro está prog , la persona al acceder al sistema recibirá la pantalla de ejecución del programa prog y al terminar la ejecución saldrá inmediatamente con un logout. Imagina cuanto podemos aumentar la seguridad con este simples truco.
Te acuerdas que te mencioné de la familia Shell? Exactamente, vamos a comenzar a entender esto: el Shell, que se vale de la imagen de una concha envolviendo el sistema operativo propiamente dicho, es el nombre genérico para tratar los hijos de esta idea que, con el correr de los años de existencia del sistema operativo Unix fueron apareciendo. Actualmente existen diversos “sabores” de Shell, entre ellos destaco el sh (Bourne Shell), el ksh (Korn Shell), bash (Bourne Again Shell) y el csh (C Shell).
Una visión rápida em los Principales Sabores de Shell
Bourne Shell (sh)
Desarrollado por Stephen Bourne de la Bell Labs (de AT&T donde también fue desarrollado el Unix), este fue durante muchos años el Shell patrón del sistema operativo Unix. Es también llamado de Standard Shell por haber sido durante varios años, el único y hasta hoy es el mas utilizado ya que fue transportado para todos los ambientes Unix y distros Linux.
Korn Shell (ksh)
Desarrollado por David Korn, también de la Bell Labs, es un superconjunto del sh, o sea, posee todas las facilidades del sh y a ellas se agregaron muchas otras. La compatibilidade total con el sh esta atrayendo a muchos usuarios y programadores de Shell para este ambiente.
Boune Again Shell (bash)
Este es el Shell mas moderno y cuyo número de adeptos crece mas en todo el mundo, sea por ser el Shell default de Linux, su sistema operativo natural, o sea por su gran diversidad de comandos, que incorpora inclusive diversas instrucciones características del C Shell.
C Shell (csh)
Desarrollado por Bill Joy de la Berkley University es el Shell mas utilizado en ambientes *BSD e Xenix. La estrutura de sus comandos es bastante similar al del lenguage C. Su gran pecado fue ignorar la compatibilidad con el sh, partiendo por un camino propio.
Además de estos Shells existen otros, pero contigo voy a hablar solamente sobre los tres primeros, tratandolos genéricamente por Shell y señalando las peculiaridades de cada uno que eventualmente tengan.
Explicando el funcionamento de Shell
El Shell es el primer programa al que accedes al "loguearte" en Linux. Es él quien va a resolver una cantidad de cosas para no cargar al kernel con tareas repetitivas, aliviandolo para tratar asuntos mas importantes. Como cada usuario posee su propio Shell interponiendose entre él y el Linux, es el Shell quien interpreta los comandos que son tecleados y examina sus sintaxis, pasándolos desmenuzados para su ejecución.
- Alto ahí, no corra tanto! Ese trabajo de interpretar comandos no tiene nada que ver con intérprete, no es cierto?
- Tiene que ver si, la verdad el Shell es un interpretador (o intérprete realmente) que trae consigo un poderoso lenguaje con comandos de alto nivel, que permite la construcción de loops (lazos), tomas de decisión y de almacenamiento de valores en variables, como te voy mostrar ahora.
Voy a explicarte las principales tareas que el Shell cumple, por su orden de ejecución. Prestale mucha atención a este orden porque es fundamental para comprender el resto de nuestra conversación.
Exámen de la Línea de Comandos
En este exámen el Shell identifica los caracteres especiales (reservados) que tienen significado para la interpretación de la línea, inmediatamente después verifica si la línea pasada es una asignación o un comando.
Asignación
Si el Shell encuentra dos campos separados por un símbolo de igual (= ) sin espacios en blanco entre ellos, identifica esta secuencia como una asignación.
Exemplos
$ ls linux
linux
En este ejemplo el Shell identificó el ls como un programa y el linux como un parámetro pasado para el programa ls .
$ valor=1000
En este caso, por no haber espacios en blanco (y así identificamos que el espacio en blanco es un de los caracteres reservados) el Shell identificó una asignación y colocó 1000 en la variable valor .
Nunca Haga:
$ valor = 1000
bash: valor: not found
Aqui el Bash tomo la palabra valor aislada por espacios en blanco y juzgó que tu habías mandado ejecutar un programa llamado valor, al cual estarías pasando dos parámetros: = e 1000 .
Comando
Cuando se escribe una línea en el prompt de Linux, esta es dividida en pedazos separados por espacios en blanco: el primer pedazo es el nombre del programa y su existencia sera comprobada; identifica en seguida, en este orden: opciones/parámetros, redireccionamentos y variables.
Si el programa identificado existe, el Shell verifica los permisos de los archivos involucrados (inclusive el propio programa), dando un señal de error en caso de que tu no estés autorizado a ejecutar esta tarea.
Resolución de Redireccionamentos
Después de identificar los componentes de la línea que tecleaste, el Shell parte para la resolución de redireccionamentos.
El Shell tiene incorporado a su elenco de ventajas lo que llamamos el redireccionamento, que puede ser de entrada (stdin ), de salida (stdout ) o de errores (stderr ), de acuerdo a como te explicaré a continuación.
Substitución de variables
En este punto, el Shell verifica si las eventuales variables (parámetros comenzados por $ ), encontradas en el campo del comando, están definidas y las substituye por sus valores actuales.
Substitución de Meta caracteres
Si algún metacaracter (* , ? ou [] ) es hallado en la línea de comando, es aquí que será substituido por sus posibles valores.
Suponiendo que el único archivo que comienza por la letra n en su actual directorio sea un directorio llamado nombregrandeparacaramba , si tu haces:
$ cd n*
Como hasta aquí quien está trabajando su línea es el Shell y el comando (programa) cd todavía no fue ejecutado, el Shell transforma el n* en nombregrandeparacaramba y el comando cd será ejecutado con éxito.
Pasa línea de Comando para el kernel
Completadas las anteriores tareas, el Shell monta la línea de comandos, ya con todas las substituciones hechas, llama el kernel para ejecutarla en un nuevo Shell (Shell hijo), recibiendo un número de proceso (PID o Process IDentification) y permanece inactivo, durmiendo una siestecita, durante la ejecución del programa. Una vez finalizado este proceso (junto con el Shell hijo), recibe nuevamente el control y, exhibiendo un prompt, muestra que está listo para ejecutar otros comandos.
Descifrando la Piedra de Roseta
Para sacarte aquella sensación que tienes cuando ves un script Shell, que mas parece una sopa de letras o un jeroglífico, te mostraré los principales caracteres especiales para que puedas salir por ahí como el Jean-François Champollion descifrando la Piedra de Roseta (vale la pena dar una "googlada" para descubrir quién es este tipo).
caracteres que cambian el significado
Por eso mismo, cuando deseamos que el Shell no interprete un carácter especial, debemos "esconderlo" de él. Eso puede hacerse de tres formas distintas:
Apóstrofe o plic (' )
Cuando el Shell ve una cadena de caracteres entre apostrofes (' ), él saca los apostrofes de la cadena y no interpreta su contenido.
$ ls linux*
linuxmagazine
$ ls 'linux*'
bash: linux* no such file or directory
En el primer caso el Shell "abrió" el asterisco y descubrió el archivo linuxmagazine para listar. En el segundo, los apostrofes evitaron la interpretación del Shell y dio la respuesta que no existe el archivo linux* .
Contrabarra o Barra Invertida (\)
Idéntico a los apostrofes excepto que la barra invertida evita la interpretación del carácter que la sigue solamente.
Suponga que accidentalmente has creado un archivo llamado * (asterisco) – que algunos sabores de Unix permiten - y deseas eliminarlo. Si tu hicieras:
$ rm *
Tendrías un gran problema, ya que el rm borraría todos los archivos del directorio corriente. La mejor forma de hacerlo es:
$ rm \*
De esta forma, el Shell no interpretaría el asterisco, y por consiguiente no haría su abertura
Haz la siguiente experiencia científica:
$ cd /etc
$ echo '*'
$ echo \*
$ echo *
Viste la diferencia? Entonces no se precisa explicar mas.
Aspas (" )
Exactamente igual a apostrofe excepto que, si la cadena entre aspas contiene un signo de pesos ($ ), un acento invertido (` ), o una barra invertida (\ ), estos caracteres serán interpretados por el Shell.
No debes preocuparte ahora con todo eso, todavía no te di ejemplos del uso de las aspas porque todavía no conoces el signo de pesos ($ ) ni el acento grave (` ). De aquí en adelante veremos con mucho detalle el uso de estos caracteres especiales, lo mas importante es entender el significado de cada uno.
caracteres de redireccionamento
La mayoría de los comandos tiene una entrada, una salida y puede generar errores. Esta entrada es llamada Entrada Patrón o stdin y su default es el teclado del terminal. Análogamente, la salida del comando es llamada Salida Patrón o stdout y su default es la pantalla del terminal. Hacia la pantalla también son enviados por default los mensajes de error oriundos del comando, y que en este caso es la llamada Salida de Error Patrón o stderr . Veremos ahora como alterar este estado de cosas.
Vamos a hacer un programa tartamudo. Para eso haz:
$ cat
El cat es una instrucción que lista el contenido del archivo especificado para la Salida Patrón (stdout ). En el caso que la entrada no esté definida, el espera los datos de la stdin . Mira, como yo no especifiqué la entrada, el está esperándola por el teclado (Entrada Patrón) y como tampoco no cité la salida, lo que yo escriba irá hacia la pantalla (Salida Patrón) haciendo de esta forma, como había propuesto un programa tartamudo. Prueba, prueba, el teclado no muerde!
Redireccionamento de la Salida Patrón
Para especificar una salida de programa usamos el > (mayor que) o el >> (mayor, mayor) seguido del nombre del archivo al que se desea mandar la salida.
Vamos a transformar el programa tartamudo en un editor de textos (que pretensión eh!).
$ cat > Arch
El cat continua sin tener una entrada especificada, por lo tanto está aguardando que los datos sean escritos, sin embargo su salida está siendo desviada hacia el archivo Arch . De esta forma, todo lo que esta siendo escrito está yendo hacia Arch , de forma que hicimos el editor de textos mas corto y pobre del planeta.
Si ejecutas nuevamente:
$ cat > Arch
Los datos contenidos en Arch se perderán, ya que antes del redireccionamento el Shell creará un Arch vacio. Para colocar mas informaciones en el final del archivo deberias haber hecho:
$ cat >> Arch

Como ya te habia dicho, el Shell resuelve la linea y despues manda el comando para su ejecución. Asi, si tu redireccionas la salida de un archivo hacia el mismo, primero el Shell "vacia" este archivo y después manda el comando para su ejecución, y de esta forma acabas de perder el contenido de tu querido archivo.
Con esto notamos que el >> (mayor mayor) sirve para incluir texto al final del archivo.
Redireccionamento de la Salida de Error Patrón
Así como el default del Shell es recibir los datos del teclado y mandar las salidas hacia la pantalla, los errores también serán enviados hacia la pantalla si tu no especificas hacia donde deverán ser enviados. Para redireccionar los errores usa 2> SalidaDeError . Fijate que entre el número 2 y el símbolo de mayor (> ) no existe espacio en blanco.

Presta atención! No confundas >> con 2> . El primero anexa datos al final de un archivo, en cuanto el segundo redirecciona la Salida de Error Patrón ( stderr ) hacia el archivo que ha sido designado. Esto es importante!
Suponte que durante la ejecución de un script tu puedes, o no (dependiendo del rumbo tomado por la ejecución del programa), haber creado un archivo llamado /tmp/seraqueexiste$$ . Para no dejar basura en tu disco, al final del script deberías colocar esta línea:
$ rm /tmp/seraqueexiste$$
En caso de no existir el archivo, seria enviado hacia la pantalla un mensaje de error. Para que eso no ocurra se debe hacer:
$ rm /tmp/seraqueexiste$$ 2> /dev/null
Sobre el ejemplo que acabamos de ver tengo dos consejos a dar:
Consejo # 1
El $$ contiene el PID, o sea, el número de su proceso. Como Linux es multiusuario, es de buenos modales anexar siempre el $$ a los nombre de los archivos que serán usados por varias personas para que no haya problemas de propriedad, o sea, en caso que nombrases tu archivo simplemente como seraqueexiste , el primero que lo usase (creándolo entonces) seria su dueño y todos los otros obtendrian un error cuando intentasen grabar algo en él.
Para que hagas un test de la Salida de Error Patrón te voy a dar otro ejemplo, escribe directamente en el prompt del Shell:
$ ls noexiste
bash: noexiste no such file or directory
$ ls noexiste 2> archivodeerrores
$
$ cat archivodeerrores
bash: noexiste no such file or directory
En este ejemplo, vimos que cuando hicimos un ls en noexiste , obtuvimos un mensaje de error. Después, redireccionamos la Salida de Error Patrón hacia archivodeerros y executamos el mismo comando, recibiendo solamente el prompt en la pantalla. Cuando listamos el contenido del archivo para el cual fue redireccionada la Salida de Error Patron, vimos que el mensaje de error habia sido almacenado en él. Haz este test.
Dica # 2
- Quién es ese tal de /dev/null ?
- En Unix existe un archivo fantasma. Llamase /dev/null . Todo lo que es enviado a este archivo desaparece. Se parece a un Agujero Negro. En el caso del ejemplo, como no me interesaba guardar el posible mensaje de error proveniente del comando rm , lo redireccioné para este archivo.
Es interesante notar que estos caracteres de redireccionamento son acumulativos, o sea, si en el ejemplo anterior hicieramos:
$ ls noexiste 2>> archivodeerrores
el mensaje de error proveniente del ls seria añadido al final de archivodeerrores .
Redireccionamento de la Entrada Patrón
Para hacer el redireccionamento de la Entrada Patrón usamos el < (menor que).
- Y para que sirve eso? - me vas a preguntar.
- Déjame darte un ejemplo que vas a entender rapidito.
Supone que quieres mandar un mail a tu jefe. Para el Jefe queremos lo mejor, no es así? entonces, en lugar de escribir el mail dirigiéndolo directamente al prompt de la pantalla de forma de que será imposible la corrección de una frase anterior donde, sin querer, escribiste un "nosotros va", tu editas un archivo con el contenido del mensaje y después de unas quince verificaciones sin constatar errores, decides enviarlo y para eso haces:
$ mail jefe < archivoconmailparaeljefe
Tu jefe reciberá entonces el contenido del archivoconmailparaeljefe .
Otro tipo de redireccionamento muy loco que el Shell te permite es el llamado here document. Es representado por << (menor menor) y sirve para indicar al Shell que el alcance de un comando comenza en la línea siguiente y termina cuando encuentra una línea cuyo contenido sea unicamente la etiqueta que sigue al símbolo << .
Observa a continuación el fragmento de un script, con una rutina de ftp :
ftp -ivn hostremoto << fimftp
user $Usuario $Seña
binary
get archivoremoto
fimftp
En este pedacito de programa tenemos una cantidad de detalles interesantes:
- Las opciones que usé para el
ftp (-ivn ) sirven para ir listando todo lo que está ocurriendo (—v de verbose), para no preguntar si tienes la seguridad de que deseas transmitir cada archivo (—i de interactive), y finalmente la opción —n sirve para decirle al ftp para que no solicite el usuario y su contraseña, pues estos estarán indicados por la instrucción específica (user );
- Cuando usé el
<< fimftp , estaba diciendo lo siguiente para el intérprete: - Mira aqui Shell, no hagas nada a partir de aqui hasta encontrar la etiqueta fimftp . Tu no entenderias nada, ya que son instrucciones específicas del comando ftp y tu no entiendies nada de ftp . Si solo fuera eso, seria simple, pero el mismo ejemplo dá para ver que existen dos variables ($Usuário e $Senha ), que el Shell va a resolver antes del redireccionamento. Sin embargo, la gran ventaja de este tipo de construcción es que ella permite que los comandos también sean interpretados dentro del alcance del here document, lo que también contradice lo que acabe de decir. Enseguida explico como funciona esto. No es este el momento todavía, nos faltan herramientas.
- El comando
user es del repertorio de instrucciones del ftp y sirve para pasar el usuario y la contraseña, que habian sido leídos en una rutina anterior a ese fragmento de código y colocados respectivamente en las dos variables: $Usuário y $Seña .
- El
binary es otra instrucción del ftp , que sirve para indicar que la transferencia de archivoremoto será hecha en modo binario, o sea, el contenido del archivo no será interpretado para saber se está en ASCII, EBCDIC, ...
- El
get archivoremoto le dice al ftp que saque ese archivo del hostremoto y lo traiga a nuestro host local. Si fuera para mandar el archivo, usariamos el comando put .

Un error muy frecuente en el uso de labels (como el fimftp del ejemplo anterior) es causado por la presencia de espacios en blanco antes o después del mismo. Estate muy atento en relación a esto, por que este tipo de errores causan muchos dolores de cabeza a los programadores, hasta que son detectados. Acuérdate: un label que se precie, tiene que tener una linea enterita solamente para él.
- Está bien, está bien! Ya sé que salí de viaje y entré por los comandos del ftp , escapando de nuestro asunto, que es el Shell, pero como siempre es bueno aprender algo mas y es raro que las personas estén dispuestas para enseñar...
Redireccionamento de Comandos
Los redireccionamentos que hablamos hasta aqui siempre se referían a archivos, o sea mandaban hacia archivo, recibían de archivo, simulaban archivo local, ... Lo que veremos a partir de ahora, redirecciona la salida de un comando hacia la entrada de otro. Esto es utilísimo y facilita la vida un montón. Su nome es pipe (que en inglés significa tubo, ya que él envía la salida de un comando directamente como por un caño hacia la entrada del otro) y su representación es una barra vertical (| ).
$ ls | wc -l
21
El comando ls pasó la lista de archivos para el comando wc , que cuando está con la opción –l cuenta la cantidad de lineas que recibió. De esta forma, podemos afirmar categóricamente que en mi diretorio existían 21 archivos.
$ cat /etc/passwd |sort | lp
Esta linea de comandos manda la lista del archivo /etc/passwd hacia la entrada del comando sort . Éste la clasifica y la manda para el lp que es el gerente mandamás del spool de impresión.
Caracteres de Ambiente
Cuando quieres priorizar una expresión la colocas entre paréntesis, no es así? Puede ser, a causa de la aritmética es normal que pensemos así. Sin embargo, en Shell lo que prioriza realmente son los acentos graves (` ) y no los paréntesis. Te voy a dar ejemplos del uso de los acentos graves para que lo entiendas mejor.
Si quiero saber cuántos usuarios están "logados" en el computador que administro. Puedo hacer:
$ who | wc -l
8
El comando who pasa la lista de usuarios conectados al comando wc –l que cuenta cuantas lineas recibió y lista la respuesta en la pantalla. Ahora bien, en lugar de tener un ocho suelto en la pantalla, lo que quiero es que esté colocado en medio de una frase.
Entonces, para mandar frases hacia la pantalla usamos el comando echo , veamos entonces como queda:
$ echo "Existen who | wc -l usuarios conectados"
Existen who | wc -l usuarios conectados
Epa! Que pasó?, no funcionó! Exactamente, no funcionó y no fue por causa de las aspas que coloqué, sino porque tendria que haber ejecutado el who | wc -l antes del echo . Para resolver este problema, tengo que priorizar esta segunda parte del comando com el uso de los acentos graves, haciéndolo de la siguiente forma:
$ echo "Existen `who | wc -l` usuarios conectados"
Existen 8 usuarios conectados
Para eliminar esa cantidad de espacios en blancos antes del 8 que el wc -l produjo, basta sacar las aspas. Así:
$ echo Existen `who | wc -l` usuarios conectados
Existen 8 usuarios conectados
Como dije antes, las aspas protejen todo lo que está dentro de sus límites, de la interpretación del Shell. Como para el Shell basta un espacio en blanco como separador, esa cantidad de espacios será cambiada por un único espacio, después de haber retirado las aspas (económico, eh?).
Antes de hablar sobre el uso de los paréntesis déjame explicar rapidamente acerca del uso del punto y coma (; ). Cuando estés en el Shell, siempre debes dar un comando en cada linea. Para agrupar comandos en una misma línea tenemos que separarlos por punto y coma. De esta forma:
$ pwd ; cd /etc; pwd; cd -; pwd
/home/midir
/etc/
/home/midir
En este ejemplo, listé el nombre del directorio corriente con el comando pwd , me cambié para el directorio /etc , nuevamente listé el nombre del directorio y finalmente volví para el directorio donde estaba anteriormente (cd - ), listando su nombre. Note que coloqué el punto y coma (; ) de todas las formas posibles para mostrar que no importa si existen espacios en blanco antes o después de este caracter.
Finalmente veamos el caso de los paréntesis. Observa el caso siguiente, muy parecido al ejemplo anterior:
$ (pwd ; cd /etc ; pwd;)
/home/midir
/etc/
$ pwd
/home/midir
- Qué es eso, por amor del Shell!? Yo estaba en /home/midir , me cambié para el /etc , verifiqué que estaba en ese directorio con el pwd seguiente y cuando el agrupamiento de comandos terminó, vi que continuaba en el /home/midir , como si nunca hubiera salido de alli!
- Ah! Será que es cosa de magos?
- No me confundas, amigo!! No es nada de eso! Lo interesante del uso de paréntesis es que se llama a un nuevo Shell para ejecutar los comandos que están en su interior. De esta forma, realmente fuimos para el directorio /etc , sin embargo cuando todos los comandos dentro de los paréntesis fueron ejecutados, el nuevo Shell que estaba en el directorio /etc murió y volvimos al Shell anterior cuyo directorio corriente era /home/midir . Haz otras pruebas usando cd , y ls para que dejes este concepto bien cimentado.
Ahora que ya conocemos estos conceptos observemos este ejemplo que sigue:
$ mail apoyo << FIM
> Hola apoyo, hoy a las ‘date "+%H:%M"‘
> ocurrió nuevamente aquel problema
> que ya habia informado por
> teléfono. De acuerdo con su pedido
> ahí va una lista de los archivos
> del directorio:
> ‘ls —l‘
> Abrazos a todos.
> FIM
Finalmente ahora tenemos el conocimiento necesario para mostrar lo que habiamos conversado sobre here document. Los comandos entre acentos graves (` ) tendrán prioridad y por tanto el Shell los ejecutará antes de la instrucción mail . Cuando el apoyo reciba el e-mail, verá que los comandos date y ls fueron ejecutados inmediatamente antes del comando mail , recibiendo entonces una fotografía del ambiente en el momento en que la correspondencia fue enviada.
El prompt primario default del Shell, como vimos, es el símbolo de pesos ($ ), sin embargo el Shell usa el concepto de prompt secundario, o de continuación de comando, que es enviado para la pantalla cuando hay un quiebro de linea y la instrucción no terminó. Ese prompt, es representado por un símbolo de mayor (> ), que vemos precediendo a partir de la 2ª linea del ejemplo.
Para finalizar y mezclarlo todo, debo decir que existe una construcción mas moderna que viene siendo utilizada como forma de priorizar la ejecución de comandos, como hacen los acentos graves (` ). Son las construcciones del tipo $(cmd) , donde cmd es un (o varios) comando(s) que será(n) ejecutado(s) con prioridad en su contexto.
De esta forma, el uso de acentos graves(` ) o construcciones del tipo $(cmd) sirven para el mismo fin, sin embargo para quien trabaja con sistemas operativos de diversos fabricantes (multiplataforma), aconsejo el uso de los acentos invertidos, ya que el $(cmd) no fue trasladado para todos los sabores de Shell. Aqui dentro del Bar, usaré las dos formas, indistintamente.
Veamos nuevamente el ejemplo dado para los acentos invertidos, ahora con una nueva visión:
$ echo Existen $(who | grep wc -l) usuarios conectados
Existen 8 usuarios conectados
Mira este caso:
$ Archs=ls
$ echo $Archs
ls
En este ejemplo, hice una asignación (= ) y ejecuté una instrucción. Lo que quería era que la variable $Archs , recibiese la salida del comando ls . Como las instrucciones de un script son interpretadas de arriba hacia abajo y de izquierda a derecha, la asignación fue hecha antes de la ejecución del ls . Para hacer lo que deseamos es necesario que le dé prioridad a la ejecución de este comando en perjuicio de la asignación y esto puede ser realizado de cualquiera de las maneras siguientes:
$ Archs=`ls`
o:
$ Archs=$(ls)
Para cerrar este asunto con broche de oro, vamos a ver un último ejemplo. Digamos que quiero colocar dentro de la variable $Archs la lista detallada (ls -l ) de todos los archivos comenzados por arch y seguidos de un único caracter (? ). Para eso deberia hacer:
$ Archs=$(ls -l arch?)
o:
$ Achs=`ls -l arch?`
Sin embargo, ve esto:
$ echo $Archs
-rw-r--r-- 1 jneves jneves 19 May 24 19:41 arch1 -rw-r--r-- 1 jneves jneves 23 May 24 19:43 arch2 -rw-r--r-- 1 jneves jneves 1866 Jan 22 2003 archl
- Caramba! salió todo junto!
- Eso mismo, como ya te dije, si tu dejas que el Shell “vea” los espacios en blanco, siempre que haya diversos espacios juntos, estos serán cambiados por uno solo. Para que la lista salga bien bonita, es necesario proteger la variable de la interpretación de Shell, así:
$ echo "$Archs"
-rw-r--r-- 1 jneves jneves 19 May 24 19:41 arch1
-rw-r--r-- 1 jneves jneves 23 May 24 19:43 arch2
-rw-r--r-- 1 jneves jneves 1866 Jan 22 2003 archl
- Y ahora amigo, ve practicando esos ejemplos, porque, cuando nos encontremos nuevamente, te voy a explicar una serie de instrucciones típicas de programación Shell. Chau! Ahh! Solamente una cosita mas que me estaba olvidando de decirte. En Shell, el símbolo (# ) es usado cuando deseamos hacer un comentario.
$ exit # pídele la cuenta al mozo
Cualquer duda o falta de compañia para tomar una cerveza o incluso para hablar mal de los políticos lo único que tienes que hacer es mandarme un e-mail para julio.neves@gmail.com. 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 julio.neves@uniriotec.br para informarse.
Gracias y hasta la próxima
-- HumbertoPina - 01 Sep 2006
|