next up previous
Next: Manejo de Archivos Up: Curso de GNU/Linux para Previous: Recorrido por el sistema

Subsecciones

Shell

El shell es el intérprete de comandos. En DOS normalmente el shell es el command.com, en UNIX existen muchos shell usados habitualmente.

sh
Desde la séptima edición de UNIX el shell por excelencia es el sh. Fue escrito por Steven Bourne, y es por eso que se lo suele llamar Bourne Shell. Está disponible en todas las versiones de UNIX y es lo suficientemente básico como para que funcione en todas las plataformas.

csh
Un shell un poco mejor con respecto al sh es el csh, que fue escrito por Bill Joy, y debe su nombre al lenguaje de programación C. Al hacer scripts en este shell puede utilizarse una sintaxis similar a la de C.

ksh
Otro shell, que como ventaja maneja un historial de comandos, es el ksh (korn shell). Está basado en sh, con algunos agregados muy básicos para hacerlo más amigable.

bash
Uno de los shell más avanzados, muy popular en la comunidad GNU/Linux es el bash. El nombre significa Bourne Again Shell. Tiene licencia GNU y se suele incluir como shell predeterminado en las distribuciones.

Ofrece las mismas capacidades que csh, pero incluye funciones avanzadas, tanto para el usuario como para el programador.

En particular, podremos acceder a un historial de los comandos ejecutados, que se conserva incluso al pasar de una sesión a otra, utilizando los cursores.

Además, completa los nombres de comandos y archivos automáticamente, al presionar la tecla TAB.

Hay muchas otras versiones de shell además de éstas. Pero el estilo general de todos es muy similar. Lo que estudiemos en este curso será compatible con la mayoría de ellos.


Metacaracteres

Además de ejecutar los comandos que nosotros le indicamos, el shell interpreta ciertos caracteres especiales, a estos caracteres los llamamos metacaracteres.

Cuando nosotros utilizamos algún metacaracter, los comandos no lo reciben, sino que el shell lo reemplaza por lo que corresponda, y le pasa al comando ejecutado el resultado de ese reemplazo.

Eso es lo que entendemos por interpretar: reemplazar el caracter por otro caracter o por una cadena de caracteres, según corresponda.

Metacaracteres relacionados con archivos

*
Cuando el shell encuentra un *, lo reemplaza por una lista de los archivos que concuerdan con la expresión indicada.

Por ejemplo: echo * nos mostrará todos los archivos del directorio. echo a* nos mostrará todos los archivos del directorio que comiencen con a. echo *o nos mostrará todos los archivos que terminen con o. echo /usr/local/* nos mostrará todos los archivos que estén en ese directorio.

En el caso de que no hubiera ningún archivo que concuerde con la expresión, generalmente, nos mostrará la expresión que hayamos escrito.

?
Al encontrar un ? el shell lo reemplaza por cualquier otro caracter. Es decir que la expresión que escribamos se reemplazará por todos los archivos que en esa posición tengan cualquier caracter, y en el resto de la cadena tengan lo que hemos escrito.

Por ejemplo: echo ?ola nos podría mostrar archivos como hola, sola, Pola. echo a??a, podría mostrar alla, arca, asia.

Al igual que con el *, si ningún archivo concuerda con el patrón, generalmente, nos mostrá la misma expresión que hemos escrito.

[ ]
Encerrados por los corchetes, podemos escribir un rango de caracteres con los cuales queremos que el shell concuerde.

Por ejemplo, ls [af]* nos mostrará todos los archivos que comienzan con a o con f.

Podemos además especificar un rango de caracteres, con un guión en el medio. Por ejemplo, a-z (letras minúsculas), 0-9 (números), etc. y combinarlos con caracteres individuales siempre que no sea ambigua la interpretación. (Considerar la concordancia con el caracter -).

Por ejemplo, podemos querer sólo los archivos que comienzan con números seguidos de un -, en ese caso escribiríamos ls [0-9]-*} o ls [0-9][0-9]-*, si comienzan con dos números seguidos de un -.

[]
Cuando al comienzo de la cadena que está encerrada por los corchetes encontramos el caracter ^, estamos indicando que debe concordar los caracteres que no se encuentran en el rango.

Por ejemplo, ls [^0-9]*, nos listará todos los archivos que no comiencen con un número.

Metacaracteres relacionados con comandos

Ejecutar un comando es tan sencillo como escribir el comando y apretar ENTER. Sin embargo, utilizando algunos de los metacaracteres de shell podemos combinar los comandos entre sí, y lograr resultados mucho más importantes.

;
El ; es un separador de comandos, nos permite ejecutar un comando a continuación de otro, equivalente a lo que sucedería si ejecutáramos primero uno, y al terminar ejecutáramos el siguiente.

Es decir si escribimos ls; echo Hola veremos la salida del echo a continuación de la del ls.

( )
Los paréntesis sirven para encerrar grupos de comandos, y tratarlos como si fueran uno solo.

&
El & manda el comando a background, esto quiere decir, que nos devuelve la línea de comandos inmediatamente despues de apretar Enter, mientras el comando sigue ejecutándose en segundo plano.

La ejecución de tareas en segundo plano ya se ha estudiado anteriormente, cuando se vieron los comandos relacionados con procesos. Este metacaracter funciona de manera equivalente, y sus resultados pueden corroborarse utilizando el comando jobs.

Para ver un ejemplo, vamos a usar un nuevo comando, sleep, (un comando simple que espera una determinada cantidad de segundos). Por ejemplo sleep 5, espera 5 segundos antes de devolvernos la línea de comandos.

Ahora, utilizando &: (sleep 20; echo Hola) &. Al escribirlo nos mostrará el PID del comando que estamos ejecutando, y nos devolverá el shell; 20 segundos después, veremos aparecer "Hola" en nuestra línea de comandos.

Antes de que termine de ejecutarse, podemos ejecutar jobs y observar que el proceso se está ejecutando, o bien ps y observar que el comando en ejecución es sleep.

Ejercicio: hacer un comando equivalente que nos avise que ya pasaron los cinco minutos necesarios para que hierva una pava de agua.

Además, el & nos puede servir para separar comandos: cada vez que lo utilizamos para separar comandos, mandará al comando que esté a su izquierda a background.

Otros metacaracteres

'...'
Al encontrar una cadena encerrada entre ' ', el shell tomará el contenido de la cadena literalmente, es decir, sin interpretar los metacaracteres contenidos en ella.

Por ejemplo, echo '* ?* [A-Z-]*' nos mostrará * ?* [A-Z-]*.

Notar que si no cerramos las comillas y apretamos ENTER, el shell nos mostrará una línea en blanco esperando que sigamos ingresando nuestro comando, hasta que cerremos las comillas.

$\backslash$
Utilizamos una \ para escapar el siguiente caracter. Escapar significa que el shell no lo interpretará como un metacaracter.

Por ejemplo echo \* nos mostrará un *.

#
El # es el señalador de comentario. Si el shell encuentra un # al comienzo de una palabra, descartará todos los caracteres hasta en final de línea. Por ejemplo, echo 3.1416 # Pi con un error de 0.0001 nos mostrará únicamente 3.1416.

Entrada y Salida

UNIX tiene un extenso manejo de entrada y salida, es una de las características principales que nos permite combinar pequeñas herramientas para lograr resultados más complejos.

La mayoría de los comandos UNIX que nosotros utilizamos tienen una entrada estándar, una salida estándar y una salida para errores estándar. Las denominamos stdin, stdout y stderr respectivamente.

La entrada estándard por omisión es el teclado, mientras que la salida estándard y la salida de errores son, por omisión, la pantalla.

Un comando genérico, lee datos de la entrada estándar, los procesa de alguna manera, y luego emite el resultado por la salida estándar. En el caso de que durante el proceso hubiera algún error, emitirá una aviso de ese error por la salida de errores.

El Shell se encarga de relacionar estos tres, lo cual no impide que un determinado programa maneje su entrada y su salida de una manera diferente.

$>$
El caracter > nos permite direccionar la salida estándar de un comando a un archivo. De manera que ps ax > procesos guardará en el archivo procesos la salida del ps.
$<$
El caracter < nos permite direccionar la entrada estándar de un comando desde un archivo. Por ejemplo, el comando mail nos sirve para mandar mensajes a otros usuarios, si escribimos mail user < archivo mandará un mensaje con el contenido del archivo al usuario user.
$>>$
Usar un >> en lugar de un > nos permite direccionar la salida estándar a un archivo, sin sobreescribirlo, sino que le agrega los datos que nosotros queramos al final. Si ahora hacemos ps ax >> procesos tendremos el listado de procesos dos veces en un mismo archivo.
2$>$
Utilizar 2> nos permite redirigir la salida de errores a un archivo. Por ejemplo, si ejecutamos ls archivo-feo 2> test, el error del ls, indicándonos que el archivo-feo no existe se almacenará en test.
$\vert$
Para relacionar la salida estándard de un comando, con la entrada estándard de otro comando, utilizamos el caracter |. Por ejemplo, podemos relacionar la salida de ls con la entrada de wc. Haciendo ls | wc, la salida de este comando será la cantidad de líneas, palabras y caracteres que produjo ls.

Este comando recibe el nombre de pipe, que en inglés significa cañería o tubería. Es decir que es un comando que entuba la salida de un comando con la entrada de otro.

Es interesante observar lo que sucede cuando hacemos: ls > nuevo-archivo, esto es, el archivo nuevo aparece dentro del listado que hace ls. Esto se debe a que el shell, al hacer la relación entre el archivo y el comando, crea el archivo, y luego llama al ls.

Además es necesario tener en cuenta que un comando no puede utilizar como entrada y salida un mismo archivo. Por ejemplo, al ejecutar cat archivo > archivo, el intérprete de comandos nos indicará que esto no es posible.

Ejercicios

  1. Explicar en qué se diferencian ls * y echo *.
  2. Explicar en qué se diferencian ls / y echo /.
  3. Crear un archivo que contenga la cantidad de archivos en un directorio.
  4. Crear dos archivos: a.txt, que contenga hola, y b.txt, que contenga chau. Luego concatenarlos en un archivo ab.txt.


next up previous
Next: Manejo de Archivos Up: Curso de GNU/Linux para Previous: Recorrido por el sistema
hecho por Margarita Manterola y Maximiliano Curia