¡Esta es una revisión vieja del documento!
Una Introducción a la C Shell
Este tutorial es una traducción cariñosamente wikificada por ~peron del manual “An introduction to C Shell” redactado por Bill Joy, y publicado como segundo capítulo del “UNIX Programmer's Manual” de 4.2BSD "UNIX", volumen 2C, edición de agosto de 1983 de la Universidad de Berkeley.
Introducción
Una shell es un intérprete de lenguaje de comandos. Csh es el nombre de un intérprete de comandos particular en el UNIX de la Universidad de Berkeley. El objetivo principal de csh es traducir líneas de comando escritas en una terminal en acciones del sistema, así como la invocación de otros programas. Csh es un programa de usuario como cualquiera que podrás escribir. Con suerte… csh será un programa muy útil para interactuar con el sistema UNIX.
Además de este documento, querrás consultar una copia del Manual del programador de UNIX. La documentación de csh en el manual proporciona una descripción completa de todas las características de la shell y es una referencia final para preguntas sobre la misma. Muchas palabras de este documento aparecen en cursiva. Éstas son palabras importantes; nombres de comandos. y palabras que tienen un significado especial al hablar de la shell y UNIX. Muchas de las palabras están definidas en un glosario al final de este documento. Si no sabes lo que significa una palabra, debes buscarla en el glosario.
Reconocimientos
1. Uso de C shell en la Terminal
Normalmente la shell que estarás usando cuando te loguees a texto-plano.xyz es /bin/ksh. De hecho, la mayoría de la enseñanza que verás en este tutorial aplica a ella, así también como a /bin/sh,
C Shell ya no es el intérprete de comandos por defecto en texto-plano.xyz, pero podrás utilizarla para poder seguir este histórico tutorial. Ingresa a ella primero:
csh
Normalmente, recibirás el prompt por defecto de csh: % . ¡Ya podrás continuar con el tutorial! Cuando termines y desees cerrar la C Shell y volver a tu intérprete anterior, asegúrate de ingresar el comando:
exit
La noción básica de comandos
Una shell en UNIX actúa principalmente como un medio a través del cual se invocan otros programas. Si bien tiene un conjunto de funciones integradas que realiza directamente. la mayoría de los comandos provocan la ejecución de programas que, de hecho, son externos al shell. La shell se distingue así de los intérpretes de comandos de otros sistemas por el hecho de que es simplemente un programa de usuario. y por el hecho de que se utiliza casi exclusivamente como mecanismo para invocar otros programas.
Los comandos en el sistema UNIX constan de una lista de cadenas o palabras interpretadas como el nombre de comando seguido de argumentos. De esta forma, el comando
mail bill
consta de dos palabras. La primera palabra mail nombra el comando que se ejecutará, en este caso el programa de correo que envía mensajes a otros usuarios. La shell utiliza el nombre del comando para intentar ejecutarlo por usted. Buscará en varios directorios un archivo con el nombre mail que se espera que contenga el programa de correo.
El resto de las palabras del comando se dan como argumentos del propio comando cuando se ejecuta. En este caso especificamos también el argumento bill que el programa de correo electrónico mail interpreta como el nombre de un usuario al que se le remitirá correo electrónico. En el uso normal de la terminal, podríamos usar el comando de mail de la siguiente manera:
% mail bill Tengo una pregunta referente a la documentación de csh. A mi documento parecería faltarle la sección 5. Existe dicha sección? Bill EOT %
Escribimos un mensaje para enviárselo a Bill, y concluímos dicho mensaje con un ^D (que envió un mensaje de fin de archivo al programa de correo mail).
Aquí y en todo este documento… la notación “^x” debe leerse “Control+x” y representa presionar la tecla x mientras se mantiene presionada la tecla control.
Luego, el programa de correo hizo eco de los caracteres “EOT” y transmitió nuestro mensaje. La shell imprimió los caracteres % antes y después del comando de correo para indicar que se necesitaba entrada.
Después de presentar el mensaje % , la shell leerá la entrada del comando desde nuestra terminal. Escribimos un comando completo mail bill. Luego, la shell ejecutó el programa de correo mail con el argumento bill y quedó inactiva esperando que se completara. Luego, el programa de correo leyó la entrada de nuestra terminal hasta que le indicamos fin del archivo escribiendo un ^D, tras lo cual la shell notó que el correo se había completado y nos indicó que estaba lista para leer nuevamente desde la terminal, presentando inmediatamente otro % .
Este es el patrón esencial de toda interacción con UNIX a través del shell. Se escribe un comando completo en la terminal, la shell ejecuta el comando y cuando su ejecución fue completada… solicita un nuevo comando. Si usas el editor durante una hora, la shell esperará pacientemente que termine de editar y quedará a la obediente orden suya una vez que termine de editar.
Un ejemplo de un comando útil que puede ejecutar ahora es el comando tset que establece los caracteres predeterminados para borrar y eliminar en su terminal: el carácter borrar borra el último carácter que escribió y el carácter de eliminar borra toda la línea que ha ingresado hasta el momento. Por defecto. el carácter borrar es # y el carácter eliminar es @. La mayoría de las personas que usan pantallas CRT prefieren usar el carácter de retroceso (^H) como carácter de borrado, ya que así es más fácil ver lo que ha escrito hasta ahora. Puedes hacer que esto sea cierto escribiendo
tset -e
que dice al programa tset configurar el caracter boorar, y su opción por defecto para este caracter es un caracter retroceder.
Argumentos Flag
Una noción útil en UNIX es la del argumento flag. Si bien muchos argumentos de comandos especifican nombres de archivo o nombres de usuario, algunos argumentos en lugar de aquellos, especifican una capacidad opcional del comando, la cual desearías invocar. Por convención, tales argumentos comienzan con el caracter guion medio -. Por tanto, el comando
ls
producirá un listado de archivos en el directorio de trabajo actual. la opcion -s es la opción de tamaño, y
ls -s
provoca que ls también de para cada fichero el tamaño de fichero en bloques de 512 caracteres. La sección de cada comando en el Manual de Referencia de UNIX proporciona las opciones disponibles para cada comando. El comando ls tiene una gran cantidad de opciones útiles e interesantes. La mayorías de los demás comandos no tienen opciones, o sólo tienen una o dos. No es fácil recordar las opciones de los comandos que no se usan frecuentemente, de modo que la mayoría de las utilidades de UNIX prefieren realizar sólo una o dos funciones en lugar de tener muchas difíciles de recordar.
Salida a Ficheros
Los comandos que normalmente leen la entrada o escriben la salida en el terminal también se pueden ejecutar con esta entrada y/o salida realizada en un archivo.
Supongamos que deseamos guardar la fecha actual en un archivo llamado “ahora”.
El comando date imprimirá la fecha actual en nuestra terminal. Esto se debe a que nuestra terminal es la salida estándar predeterminada para el comando de fecha y el comando de fecha imprime la fecha en su salida estándar. El shell nos permite redirigir la salida estándar de un comando a través de una notación usando el metacarácter > y el nombre del archivo donde se colocará la salida. Así el comando
date > ahora
ejecuta el comando de date de modo que su salida estándar sea el fichero ahora en lugar del terminal. Por lo tanto, este comando coloca la fecha y hora actuales en el archivo ahora. Es importante saber que el comando date no sabía que su salida iba a un archivo en lugar de a la terminal. La shell realizó esta redirección antes de que el comando comenzara a ejecutarse.
Otra cosa a tener en cuenta aquí es que no es necesario que el archivo ahora existiera antes de que se ejecutara el comando date; la shell habría creado el archivo si no existiera. ¿Y si el archivo existiera? Si hubiera existido anteriormente, ¡sus contenidos anteriores habrían sido descartados! Existe una opción de la shell llamado noclobber para evitar que esto suceda accidentalmente; se analiza en la sección 2.2.
El sistema normalmente guarda los ficheros que usted crea con > y todos los demás ficheros. Por lo tanto, el valor predeterminado es que los ficheros sean permanentes. Si desea crear un archivo que se eliminará automáticamente. puede comenzar su nombre con un carácter #. este carácter “numeral” denota el hecho de que el archivo será un archivo borrador. El sistema eliminará dichos archivos después de un par de días, o mas pronto si el espacio queda limitado. Por lo tanto, al ejecutar el comando date como se indicó anteriormente, no queremos realmente que almacene la salida para siempre, de manera que más probablemente usaríamos:
date > #ahora
Metacaracteres en la Shell
Como el caso del > indicado anteriormente, la shell tiene una gran variedad de caracteres especiales que ordenan funcionalidades especiales. Decimos que para la shell, dichas notaciones guardan significado sintáctico y semántico. Por lo general, para la shell la mayoría de los caracteres que no son letras o dígitos guardan un significado especial.
Los metacaracteres normalmente surten efecto sólo cuando la shell está leyendo nuestra entrada. No debemos que preocuparnos si usamos metacaracteres en la redacción de una carta que enviaremos a través de mail, o cuando mecanografiamos texto o introducimos datos en cualquier otro programa. Debemos tener presente que la shell sólo lee entrada cuando ha señalado el prompt % .
Mas adelante habremos de aprender brevemente una manera de citar que nos permita utilizar metacarecteres sin que la shell los trate de forma especial.
Entrada desde archivos; cañerías
Anteriormente aprendimos como redirigir la salida estándar de un comando a un fichero. También es posible redirigir la entrada estándar de un comando desde un fichero. Esto a método no es necesario ya que la mayoría de los comandos leerán desde un fichero cuyo nombre se provea como argumento. Podemos dar el comando
sort < datos
para que ejecute el comando sort con la entrada estándar. Desde donde el comando leerá normalmente la entrada es desde el fichero datos. Normalmente, recurriríamos a:
sort datos
Dejando que el comando sort abra un fichero datos para proveerse el mismo la entrada, ya que es más fácil de mecanografiar. Debemos notar que si sólo miecanografiamos:
sort
entonces el programa sor ordenaría las líneas desde la entrada estándar. Ya que no redirigimos la entrada estándar, ordenaría las líneas en la medida que las mecanografiamos en la terminal, hasta que ingresemos un ^D para indicar Fin de Fichero.
Una capacidad más útil es la posibilidad de combinar la salida estándar de un comando con la entrada estándar de otro, por ejemplo para ejecutar los comandos en una secuencia conocida como cañería. Por ejemplo, el comando
ls -s
produce normalmente un listado de los ficheros de nuestro directorio, especificando el tamaño de cada uno en bloques de 512 caracteres. Si nos interesa aprender cuál de nuestros ficheros es el más grande, podríamos querer tener esta lista ordenada por tamaño, en lugar de hacerlo por nombre (la cual es la manera por defecto en la que ordena el listado el programa ls). Podemos observar las muchas opciones de ls para ver si existe alguna opción que haga esto, pero eventualmente descubriríamos que no existe ninguna [N.d.T., en la versión de 1983 de ls, claro, en la actual existe.]. En lugar de ello, podremos usar un par de opciones simples del comando sort combinándolas con ls para lograr lo que nosotros queremos.
La opción -n de sort, especifica un ordenamiento numérico en lugar de un ordenamiento alfabético. Por tanto
Is -s | sort -n
especifica que la salida del comando ls argumentado con la opción -s deba ser entubado al comando sort argumentado con su opción de ordenamiento numérico. Esto nos proporcionará una lista de nuestros ficheros ordenada por tamaño (pero indicando al principio el más pequeño). Luego podremos utilizar la opción de ordenamiento inverso -r de sort, y el comando head en combinación con aquél, ingresando
ls -s | sort -n -r | head -5
Aquí hemos tomado un listado de nuestros ficheros ordenados alfabéticamente (cada uno con su tamaño en bloques), hemos pasado esto a la entrada estándar del comando sort pidiéndole que las ordene de forma numérica invertida (la más grande primero). Esta salida ha sido luego entubada al comando head, que nos presenta las primeras pocas líneas (en este caso, solicitamos a head las primeras 5 líneas). Por lo tanto, este comando nos presenta los nombres y tamaño de nuestros 5 ficheros más grandes.
La notación introducida anteriormente se conoce como mecanismo de caño. Los comandos separados por caracteres | resultan conectados entre sí por la shell y la salida estándar de cada uno de ellos es pasado a la entrada estándar del siguiente. El comando más a la izquierda en la cañería normalmente toma su entrada estándar de la terminal, y el comando más a la derecha volcará su salida estándar en la terminal. Mas adelante daremos otros ejemplos de cañerías al discutir el mecanismo historial; un uso importante de cañería que se ilustra allí es el de redirigir información a la impresora de líneas.
Nombres de Ficheros
Para ser ejecutados, muchos comandos necesitan los nombres de fichero como argumentos. Los nombres de ruta de UNIX consisten en una cantidad de componentes separados por una /. Cada componente excepto el último nombran un directorio en el cual reside el siguiente componente, especificando - en efecto - la ruta de directorios que debe serguirse para alcanzar el fichero. Por lo tanto, la ruta
/etc/motd
especifica un fichero en el directorio etc que es un subdirectorio del directorio raíz /. Dentro de este directorio se encuentra el fichero denominado motd que significa “mensaje del día”. Un nombre de ruta comenzado con una barra / se dice que es absoluto ya que está especificado desde la parte absolutamente superior de la jerarquía de directorios completa (la raíz). Los nombres de ruta que no comienzan con / se interpretan como el directorio de trabajo actual, el cual es, por defecto, su directorio home y puede cambiarse dinámicamente con el comando de cambio de directorio cd. Tales nombres de ruta se dicen que son relativos al directorio de trabajo, ya que se encuentra iniciando su búsqueda desde el directorio de trabajo,y descendiendo a los niveles inferiores de la jerarquía de directorio para cada componente del nombre de ruta. Si el nombre de ruta no contiene barra alguna, entonces el fichero está contenido en el directorio de trabajo actual, y la ruta simplemente consiste en el nombre de fichero en este directorio. Los nombres de ruta absolutos no tienen relación al directorio de trabajo.
La mayoría de los nombre de ficheros consisten en una cantidad de caracteres alfanuméricos y puntos .. De hecho, en los nombres de archivo pueden usarse todos los caracteres impresos exceptuando la barra /. Es inconveniente usar la mayoría de los caracteres no alfabéticos en los nombres de fihero porque muchos de ellos tienen significado especial para la shell. El caracter punto . no es un metacaracter de la shell, y a menudo se utiliza para separar la extensión del nombre de archivo de la base del nombre. Por tanto
prog.c prog.o prog.errs prog.output
son cuatro ficheros relacionados. Comparte la porción base (una porción base es la parte del nombre que queda por delante del . final, y que sigue a los caracteres que no sean .. El fichero prog.c podría ser el código fuente de un programa de lenguaje C, el fichero prog.o podría el fichero de código objeto correspondiente, el fichero prog.errs los errores resultantes de una compilación del programa, y el fichero prog.output la salida de un programa ejecutado.
Si deseamos referirnos a los cuatro ficheros a la vez en un comando, podríamos utilizar la notación
prog.*
Esta palabra antes de que el comando del cual es un argumento sea ejecutado, resulta expandida por la shell en una lista de nombres que comienzan con prog, El caracter * aquí coincide con cualquier secuencia de caracteres en un nombre de fichero (incluyendo un secuencia vacía). Los nombres que coinciden son ordenados alfabéticamente y puestos en la lista de arguemntos del comando. Por lo tanto el comando
echo prog.*
dará eco a los nombres
prog.c prog.errs prog.o prog.output
Note que los nombres están ordenados aquí, y en un orden distinto al que listamos arriba. El comando echo recibe cuatro palabras como argumentos, incluso aunque sólo mecanografiamos directamente una palabra como argumento. Las cuatro palabras fueron generados por la expansión de nombre de fichero de esa única palabra de entrada.
También hay disponibles otras notaciones para expansión de nombre de fichero. El caracter ? coincide con cualquier caracter único en un nombre de fichero. Por tanto
echo ? ?? ???
Dará como eco una línea de nombres de fichero; primero aquellos con nombres de un solo caracter, luego aquellos con nombres de dos caracteres, y finalmente aquellos con nombres de tres caracteres. Los nombres de cada longitud serán independientemente ordenados.
Otro mecanismo consiste en en entrecorchetado, usando una secuencia de caracteres entre [ y ]. Esta metasecuencia coincide con cualquier caracter único del conjunto entre corchetes. Por tanto.
prog.[co]
coincidirá con
prog.c prog.o
del ejemplo anterior. También podemos poner dos caracteres rodeando un - en una notación que denota un rango. Por tanto
cap.[1-5]
podría concidir los ficheros
cap.l cap.2 cap.3 cap.4 cap.5
si existiesen. Esto es la abreviación para
cap.[12345]
y es, por ello, equivalente en todo sentido.
Otro punto importante a notar es que si una lista de palabras argumento de comando (una lista argumental) contiene sintaxis de expansión de nombre de fichero, y si esta sintaxis de expansión de nombre de fichero falla en hacer coincidir cualquier nombre de fichero existente, en tal caso la shell considerará esto como error y presentará un diagnóstico
No match.
y no ejecutará el comando.
Otro punto muy importante es que los ficheros con el caracter \ al comienzo del nombre son tratados especialmente. Ni el * ni el ? o el mecanismo de entrecorchetado [ y ] encontrarán coincidencia. Esto impide coincidir accidentalmente los nombres . y .. del directorio de trabajo - los cuales tienen significados especiales para el sistema - así como otros ficheros tales como .cshrc, que no son visibles normalmente. Discutiremos el rol especial del fichero .cshrc más adelante.
Otro mecanismo de expansión de nombre de fichero da acceso al nombre de ruta del directorio home de otros usuarios. Esta notación consiste en el caracter tilde ~, seguida por el nombre de login de otro usuario. Por ejemplo, la palabra ~bill dirigirá al nombre de ruta /usr/bill (siempre que el directorio home del tal Bill sea /usr/bill, claro está). Como en grandes sistemas, los usuarios pueden tener directorios de login distribuidos a lo largo de muchos volúmenes de disco diferentes, con diferente nombres de directorio prefijo, esta notación ofrece una manera confiable de acceder a los ficheros de otros usuarios.
Un caso especial que incumbe a esta notación es el de un tilde ~ aislado, por ejemplo ~/mbox. Esta notación resulta expandida por la shell para representar al fichero mbox en su propio directorio home, por ejemplo, en /usr/bill/mbox para mi en Ernie Co-vax, la máquina VAX del Dpto. de Ciencias del Cómputo de la universidad de California Berkeley, donde fue preparado este documento. Esto puede resultar muy útil si usted ha usado cd para cambiar a otro directorio, y ha encontrado un fichero que desea copiar con cp. Si doy el comando
cp esefichero ~
la shell expandirá dicho comando a
cp esefichero /usr/bill
ya que mi directorio home es /usr/bill.
Existe también un mecanismo que usa los caracteres de abrir llave { y cerrar llave } para abreviar un conjunto de palabras que constan de partes comunes pero no pueden ser abreviadas a través de los mecanismos anteriormente nombrados ya que no son ficheros, o son nombres de ficheros que aún no existen y por lo tanto no pueden ser descriptos convenientemente aún. Tal mecanismo será descripto bastante mas adelante, en la sección 4.2 ya que se usa con poca frecuencia
Citado
Ya hemos visto cierta cantidad de metacaracteres utilizados por la shell. Estos metacaracteres tienen una complicación dificultosa: no podemos usarlos directamente como partes de palabras. Por lo tanto el comando
echo *
no dará como eco el caracter *. O bien dará como eco una lista ordenada de nombres de ficheros del directorio de trabajo actual, o bien imprimirá el mensaje No match si no existen ficheros en el directorio de trabajo.
El mecanismo recomendado para poner caracteres que no son números, dígitos /, ., o - en una palabra argumento de un comando es apostrofarlo (encerrarlo entre apóstrofos '...'.. Por ejemplo:
echo '*'
Existe un caracter especial signo cierre de admiración ! que es es utilizado por el mecanismo historial de la shell y el cual no puede ser anulado apostrofándo de esta manera '!'. Para impedir su significado especial, tanto el signo de cierre de admiración ! como el caracter apóstrofo ' en sí deben ser precedidos por una único caracter de barra invertida \. Por tanto
echo \'\!
imprime
'!
Estos dos mecanismos resultan suficientes para poner cualquier caracter impreso en una palabra que es un argumento de un comando de la shell. Pueden combinarse, como en
echo \''*'
lo que imprime
'*
ya que la primer barra invertida \ anuló el primer apóstrofo ' y el asterisco * aparecía entre apóstrofos '.
Suspensión de Comandos
Cuando ejecuta un comando y la shell aguarda su finalización, existen varias maneras de forzar su interrupción. Por ejemplo, si ingresa el comando
cat /etc/passwd
El sistema presentará en su terminal una copia de una lista de todos los usuarios del sistema. Es probable que esta presentación continúe por varios minutos, a no ser que la interrumpa [N.d.T en la VAX 11/750 de Berkeley no era particularmente veloz y tenía cientos de usuarios!]. Puede enviar una señal INTERRUPT al comando cat presionando la tecla DEL o RUBOUT de su terminal. Ya que cat no tiene precaución cierta de evitar o considerar dicha señal de otra forma, la señal INTERRUPT provocará su finalización. La shell nota que el comando cat ha finalizado y ofrecerá un prompt con % nuevamente. Si presiona INTERRUPT nuevamente, la shell simplemente repetirá su prompt ya que - en lugar de interrumpirse al igual que cat, lo que tendría el efecto de cerrar su sesión - la shell interpreta las señales INTERRUPT y escoge continuar ejecutando comandos en lugar de finalizar.
Otra manera en la cual muchos programas pueden finalizar su ejecución es al recibir un mensaje de fin-de-fichero en su entrada estandar. Por este motivo el programa mail en el primer ejemplo anterior terminaba cuando presionábamos ^D, lo que genera un fin-de-fichero desde la entrada estándar [N.d.T: el teclado]. La shell también finaliza cuando obtiene un fin-de-fichero, a lo que presentará el mensaje logout; UNIX entonces cierra su sesión de terminal. Esto significa que si ingresa demasiadas ^D, podría accidentalmente desligarse del sistema, la shell cuenta con un mecanismo para impedirlo. Esta opción ignoreeof será discutida en la sección 2.2
Si la entrada estándar de un comando se haya redirigida desde un fichero, entonces por lo general finalizará cuando el fichero que funciona de entrada llegue al final. Por tanto, si ejecutamos
mail bill < preparado.txt
el comando mail finalizará sin que ingresemos ^D. Esto se debe a que leerá el fichero preparado.txt hasta alcanzar su fin-de-fichero, el cual pusimos un mensaje para Bill con un programa editor. También podríamos haber hecho
cat preparado.txt | mail bill
ya que el comando cat entonces habría presentado el texto a través del caño a la entrada estándar del comando mail. Cuando el comando cat hubiese terminado de presentarlo habría finalizado, clausurando la tubería y el comando mail habría recibido un fin-de-fichero desde él, finalizando como consecuencia. Si bien el resultado es el mismo, esta forma de utilizar un caño parece más complicado que refirigir la entrada de un fichero, de modo que es más probable usar la primer forma. Estos comando podrían también haber sido detenidos enviándoles un INTERRUPT.
Otra posibilidad para suspender un comando es suspender su ejecución temporalmente, lo que nos da la posibilidad de posteriormente continuar su ejecución. Esto se realiza enviando una señal STOP por medio de ^Z. Esta señal provoca que todos los comandos en ejecución en la terminal - usualmente uno, pero pueden ser varios en caso de que la tubería se encuentre en ejecución - queden suspendidos, pero no son afectados por la señal STOP de otra manera de forma alguna.
Mientras el comando original permanezca suspendido, pueden ejecutarse otros comandos cualquiera. El comando suspendido puede ser continuado por medio del comando fg sin argumentos. La shell entonces informará cuál es el comando cuya ejecución continuará, y provocará que éste prosiga su anterior ejecución. La suspensión no afecta de manera alguna la ejecución del comando, a no ser que cualquier fichero de entrada en uso del comando suspendido sea alterado de alguna manera durante la suspensión. Esta funcionalidad puede resultar muy útil durante la edición, de necesitarse revisar otro fichero antes de continuar. A continuación, se da un ejemplo de una suspensión de comando:
% mail harold Alguien me acaba de copiar un fichero enorme en mi directorio de usuario. El fichero se denomina ^Z Stopped % ls tremenda_broma prog.c prog.o % jobs [1] + Stopped mail harold % fg mail harold "tremenda_broma". ¿Sabes quién lo hizo? EOT %
En este ejemplo, un usuario está enviando un mensaje a Harold pero olvida el nombre del fichero que quería mencionarle. Suspende el comando mail ingresando ^Z. Una vez que la shell nota que el programa de correo está suspendido, presenta 'Stopped' y le ofrece su prompt, aguardando un nuevo comando. Luego el individuo ingresa el comando ls para recordar el nombre del fichero en cuestión. Usa el comando jobs para descubrir cuál comando se encuentra suspendido, y consecuentemente ingresa el comando fg para continuar la ejecución del único programa detenido, el mail a Harold. Luego continuó dando entrada a mail, y una vez concluída la redacción, la finalizó con ^D, que indica el final del mensaje ante lo cual el programa mail presentó EOT de fin-de-transmisión.
El comando jobs presenta el listado de los comandos se encuentran suspendidos. La orden ^Z solo debería mecanografiarse al comienzo de línea, pues si se envía una señal desde el teclado en en cualquier lugar distinto al comienzo de la línea, descarta (“borra”) toda la línea. Esto mismo sucede con las señales INTERRUPT y QUIT también. Para más información sobre suspender trabajos y controlarlos se ofrece en la seccion 2.6.
Si escribe o ejecuta programas que no están completamente depurados, puede ser necesaria su interrupción de manera poco ortodoxa. Esto puede lograrse enviando la señal QUIT, lograda mecanografiando ^\. No sería extraño que esto provoque que la shell presente un mensaje similar a :
Quit (Core dumped)
indicando que un fichero core conteniendo información sobre el estado del programa a.out ha sido creadodo cuando la señal QUIT produjo la terminación. Puede examinar este fichero por sí mismo, o bien enviar información al autor del programa informándole dónde está el fichero core.
Si corre comandos en segundo plano (según lo explicado en la seccion 2.6), entonces dichos comandos ignorarán las señales INTERRUPT y QUIT en el terminal. Para detenerlas debe utilizar el comando kill.
Si desea examinar detenidamente la salida de un comando sin hacer que el mismo desaparezca de la pantalla como cuando recurrimos a interrumpir la salida del comando cat /etc/passwd, usted podrá usar el comando
more | /etc/passwd
El programa more pausa tras cada pantallazo, y presenta el mensaje - - More- -, en cuyo momento usted podrá presionar la barra espaciadora para obtener otro pantallazo, o Retorno para obtener otra línea, o una q para finalizar el programa more. También puede usar more como filtro. Por ejemplo
cat /etc/passwd | more
funciona de forma similar al comando more de ejecución directa que se indicó anteriormente.
Para detener la presentación en el terminal de la salida de comandos sin involucrar a more, puede usar la tecla ^S para pausarla. Podrá continuar la presentación en el terminal al presionar ^Q (o cualquier otra tecla, pero por lo general se utiliza ^Q pues esta sólo reinicia la presentación de salida, y no se convierte en entrada de otros comandos posibles del programa que está usted ejecutando).
Podrá operar este método adecuadamente con terminales de baja velocidad, pero con 9600 baudios o más encontrará dificultoso ingresar ^S y ^Q lo suficientemente rápido como para paginar adecuadamente la salida. Este es el motivo por el cual se recurre por lo general al programa more.
Una posibilidad adicional es recurrir al caracter de descartar-salida ^O. Al tipear este caracter, toda la salida del comando actual se descarta (rápidamente) hasta producirse la siguiente lectura de entrada, o hasta la aparición del siguiente prompt. Puede utilizar esto para permitir la finalización de un comando sin tener que sufrir grandes cantidades de salida en un terminal lento. ^O opera como un comnutador, de manera que el descarte puede conmutarse ingresando nuevamente ^O mientras se produce el descarte de salida.
¿Ahora qué?
Hasta ahora hemos visto varios mecanismos de la shell y aprendimos mucho sobre la forma en la cual esta funciona. Las secciones restantes avanzarán más en el funcionamiento interno de la shell, pero seguramente querrá probar usando la shell csh antes de continuar.
La siguiente sección introducirá muchas funcionalidades particulares a csh, de modo que debe cambiarse la shell a csh antes de comenzar a leerla.
Ahora está listo para intentar usar csh.
2. Detalles de la Shell para Usuarios de Terminal
Inicio de la shell y terminación
Cuando inicie sesión en el sistema, éste iniciará una shell, que ingresará a su directorio home y comenzará por leer los comandos del un fichero llamado .cshrc localizado en dicho directorio. Todas las shells que eventualmente inicie durante su sesión de terminal leerán este fichero. Mas adelante veremos qué tipos de comandos es útil colocar allí, por ahora no es necesario contar con este fichero, y la shell no se quejará por su ausencia.
Una shell de login, ejecutada tras el inicio de su sesión al sistema - tras leer los comandos contenidos en .cshrc - leerá comandos contenidos en un fichero .login (también en su directorio home). Este fichero contiene aquellos comandos los cuales usted desea ejecutar cada vez que inicie sesión en el sistema UNIX. Mi fichero .login tiene el siguiente aspecto:
set ignoreeof set mail=(/usr/spool/mail/bill) echo "${prompt}users" ; users alias ts \ 'set noglob ; eval `tset -s -m dialup:cl00rv4pna -m plugboard:?hp2621nl *`'; ts; stty intr ^C kill ^U crt set time=15 history=10 msgs -f if (-e $mail) then echo "${prompt}maiI" mail endif
Este fichero contiene varios comandos para que UNIX los ejecuta cada vez que inicio mi sesión de terminal. El primero de ellos es un set. Este comando es interpretado en forma directa por la Shell, y configura la variable de shell ignoreeof, que provoca que la shell no me cierre la sesión si presiono ^D. En lugar de ello utilizo el comando logout para cerrar la sesión del sistema. Al establecer la variable mail, le pido a la shell que revise los correos entrantes por mí; cada 5 minutos la shell revisa este fichero y me informa si me llegó correo electrónico. Una alternativa en lugar de usar tal set es colocar en su lugar el comando
biff y
lo que hará que se me notifique inmediatamente al arribo de correo (mostrándoseme unas pocas primeras líneas del nuevo correo).
Posteriormente configuré la variable de shell time a 15, lo que hace que la shell automáticamente imprima líneas de estadística para aquellos comandos cuya ejecución requiera al menos 15 segundos de tiempo de CPU. La variable history se configura a 10, indicando que deseo que la shell recuerde los últimos 10 comandos que mecanografié en su listado de historial (descripto mas adelante).
Creé un alias “ts” que ejecuta un comando tset configurando los modos de terminal. Los parámetros de tset indican los tipos de terminal que uso a menudo cuando no estoy en el puerto normal de la VAX. Luego ejecuto ts y también uso el comando stty para cambiar el caracter de interrupción a ^C y el caracter de eliminar línea a ^U.
Luego corro el programa msgs que me provee cualquier mensaje de sistema que no hubiese visto antes; la opción -r le impide decirme cualquier cosa si no hay mensajes nuevos. Finalmente, si mi fichero de casilla de correo existe, entonces ejecuto el programa mail para procesar mi correo.
Cuando los programas mail y msgs terminan, la shell finalizará de procesar mi fichero .login y comenzará a leer comandos desde el terminal, saludando a cada uno de ellos con el prompt % . Cuando cierro sesión (ejecutando el comando logout) la shell imprimirá logout y ejecutará comandos del fichero .logout si éste está presente en mi directorio home. Luego de aquello, la shell terminará y UNIX me desconectará del sistema. Si el sistema no se apaga, recibiré un nuevo mensaje de inicio de sesión. En cualquier caso, luego del mensaje logout la shell estará conminada a terminar, y no tomará en cuenta otra entrada desde mi terminal.
Variables de la Shell
La shell mantiene un conjunto de variables. Vimos anteriormente las variables history y time que tenían valores de 10 y 15. De hecho, cada variable de shell cuenta como valor un arreglo de cero o mas cadenas. Las variables de la shell pueden recibir valores por medio del comando set. Tiene varias formas, la más útil de las cuales fue indicada anteriormente y es
set nombre=valor
Las variables de shell pueden utilizarse para almacenar valores que deben ser usados por posteriores comandos a través del mecanismo de sustitución. Las variables de shell más comúnmente referenciadas son aquellas a las cuales la shell misma refiere. Sin embargo, al modificar los valores de dichas variables, uno puede afectar directamente el comportamiento de la shell.
Una de las variables más importantes es la variable path. Ella contiene una secuencia de nombres de directorio que la shell analizará al buscar comandos. El comando set sin argumentos presenta los valores asignados de todas las variables definidas (usualmente decimos “establecidas”) en la shell. Los valores por defecto de path presentados por set son
% set argv () cwd /usr/bill home /usr/bill path (. /usr/ucb /bin lusr/bin) prompt % shell /bin/csh status 0 term cl00rv4pna user bill %
Esta salida indica que la variable path apunta al directorio actual ., y luego a los directorios /user/ucb, /bin y /usr/bin. Los comandos que pueden escribir podrían estar en . (usualmente uno de sus directorios). Los comandos desarrollados en Berkeley residen en /usr/ucb, mientras que los comandos desarrollados en los Laboratorios Bell residen en /bin y /usr/bin.
Cierta cantidad de programas desarrollados localmente en el sistema residen en el directorio /usr/local. Si deseamos que todas las shells que invocamos tengan acceso a estos nuevos programas, podremos establecerlos en nuestro fichero .cshrc en nuestro directorio home mediante el comando
set path=(. /usr/ucb /bin /usr/bin /usr/local)
Intente hacer esto y tras cerrar sesión y volver a iniciarla, ejecute set nuevamente para comprobar que el valor establecido a path ha cambiado.
Una cosa que debería tener presente es que la shell examina cada directorio que ha establecido en su path y determina cuáles comandos están allí contenidos. Exceptuando el directorio actual . - el cual la shell trata especialmente - esto significa que si se agregan comandos a un directorio en su path posteriormente a la iniciar la shell, no serán necesariamente encontrados por la shell. De desear utilizar un comando que agregado de esta manera, deberá indicar primero el comando
rehash
para que la shell se refresque, lo que provocará que recalcule la tabla interna de localizaciones de comandos, de forma que poder encontrar los comandos recientemente agregados. Como toda vez que ejecuta un comando, la shell debe buscar en el directorio actual ., ponerlo al final de la especificación establecida en la path usualmente funciona de forma equivalente, reduciendo el tiempo de espera.
Otras variables incorporadas útiles son las variables home que muestra su directorio home, cwd que contiene su directorio de trabajo actual, y la variable ignoreeof (la cual puede ser configurada en su fichero .login para decirle a la shell que no salga cuando recibe un caracter fin de fichero desde un terminal, como se mencionó anteriormente). La variable ignoreeof es una de aquellas en las que la shell no le importa su valor asignado, sólo hace caso si dice set o unset para denotar q1ue están configuradas o no, respectivamente. Por lo tanto, para establecer esta variable usted simplemente indica
set ignoreeof
y para desestablecerla, usted utiliza
unset ignoreeof
Estos no le otorgan a la variable ignoreeof valor alguno, pero no se les requiere o desea en lo absoluto.
Finalmente, algunas de las otras variables incorporadas de la shell en uso son las variables noclobber y mail.
La metasintaxis
> fichero
que redirige la salida estándar de un comando, sobrescribirá y destruirá los contenidos previos de fichero. Acaso usted podría sobrescribir accidentalmente un fichero que es valioso. Si prefiere que la shell no sobrescriba ficheros de esta manera, puede indicar
set noclobber
en su fichero .login. Luego intente ordenar
date > ahora
lo que causará un diagnóstico de error si ahora ya existe. Podría mecanografiar
date >! ahora
si realmente desea sobrescribir los contenidos de ahora. El >! es una metasintaxis especial que indica que está bien “darle una paliza” a fichero [NdT: clobber significa “apalear”, y es la jerga utilizada para denotar la sobrescritura inadvertida del fichero].
El espacio en blanco entre el!y la palabraahoraes crítico, ya que!ahorainvocaría las mecanismo de historial, que tiene un efecto completamente distinto.
Historial de la shell
La shell puede mantener una lista de historial en la cual pone las palabras de los comandos anteriormente ejecutados. Es posible utilizar una notación para reutilizar comandos o palabras de los comandos en la formación de nuevos comandos. Este mecanismo puede utilizarse para repetir comandos previos o corregir errores de mecanografiado menores en los comandos.
La siguiente es una sesión de ejemplo que involucra el uso típico del mecanismo de historial de la shell. En este ejemplo tenemos un programa muy simple en lenguaje C que tiene un bug (o dos), en el fichero bug.c, el cual revisamos con cat en nuestra terminal. Luego intentamos correr el compilador CC con él, refiriendo el fichero nuevamente como !$ (lo que significa el último argumento del comando anterior). Aquí el ! es el metacaracter de invocación al mecanismo historial, mientras que el $ refiere al “último argumento” (en analogía al uso de $ en el editor ed, que significa “final de la línea”). La shell da eco del comando - tal como se hubiese mecanografiado sin recurrir al mecanismo de historial - y luego lo ejecuta. La compilación produjo un diagnóstico de error de manera que corremos el editor en el fichero que intentábamos compilar, corregimos el bug, y corrimos nuevamente el compilador de C, esta vez refiriendo a este comando simplemente como !c (lo que repite el último comando historiado que comenzaba con la letra c). Si hubiesen existido otros comandos historiados que comenzaban con la letra c, podríamos haber tenido que recurrí a especificar con mayor detalle !cc o incluso !cc:p (que hubiese impreso el último comando que comenzaba con cc pero sin ejecutarlo).
% cat bug.c
main ()
{
printf("hola) ~
}
% cc !$
cc bug.c
"bug.c", line 4: newline in string or char constant
"bug.c", line 5: syntax error
% ed !$
ed bug.c
29
4s/);/"&/p
printf("hola");
w
30
q
% !c
cc bug.c
% a.out
hello% !e
ed bug.c
30
4s/lo/lo\\n/p
printf("hola\n");
w
32
q
% !c -o bug
cc bug.c -o bug
% size a.out bug
a.out: 2784+364+1028 = 4176b = 0x1050b
bug: 2784+364+1028 = 4176b = 0xl050b
% ls -l !*
ls -1 a.out bug
-rwxr-xr-x 1 bill 3932 Dec 19 09:41 a.out
-rwxr-xr-x 1 bill 3932 Dec 19 09:42 bug
% bug
hola
% num bug.c | spp
spp: Command not found.
% ^spp^ssp
num bug.c | ssp
1 main()
3 {
4
printf("hola\n");
5 }
% !! | lpr
num bug.c | ssp | lpr
%
Luego recompilar, corremos e fichero a.out resultante, y notamos que aún hay un bug, por lo que corremos nuevamente el editor. Tras corregir el programa corremos el compilador C nuevamente, pero asociado al comando un -o bug extra indicando al compilador que coloque el binario resultante en el fichero bug en lugar del nombre por defecto a.out. El mecanismo de historial puede usarse en general en cualquier lugar de la formación de nuevos comandos y pueden colocarse otros caracteres antes y después de los comandos sustituidos.
Podemos luego correr el comando size para ver cuán grande eran las imágenes de los programas binarios que habíamos creado, y luego un comando ls -l con la misma lista argumental, denotando la lista argumenta .. Finalmente, corremos el programa bug para ver si su salida es de hecho correcta.
Para hacer un listado numerado del programa corremos el comando num en el fichero bug.c. Para comprimir las líneas en blanco en la salida de num corremos la salida a través del filtro ssp pero lo mecanografiamos erróneamente, escribiéndolo como spp. Para corregir esto usamos una sustitución de shell, colocando el viejo texto y el nuevo entre caracteres ^. Esto es similar al comando “sustituir” del editor ed. Finalmente, repetimos el mismo comando con !! pero enviamos su salida a la impresora de línea.
Existen otros mecanismos disponibles para repetir comandos. El comando history imprime cierta cantidad de comandos previos con números a través de los cuales pueden ser referenciados.
Hay una manera de referir a un comando previo buscándolo a por medio de una cadena que aparezca en el, y existe otra - menos útil - para seleccionar argumentos a incluir en un nuevo comando. Una descripción completa de todos estos mecanismos se da en las páginas man de csh, y en el Manual de Programador de UNIX.
Alias
La shell cuenta con un mecanismo de alias que puede ser utilizado para efectuar transoframciones en los comandos de entrada. Tal mecanismo puede ser utilizado para simplificar los comandos que interesan, supliendo argumentos por defecto deseados a dichos comandos, o bien para operar transformaciones a los comandos y sus argumentos. La funcionalidad de alias es similar a una facilidad por macros. Algunas de las funcionalidades obtenidas utilizando alias puede obtenerse también usando ficheros de intérprete de comanods, pero estas tomarán lugar en otra instancia de la shell, y no pueden afectar directamente el ambiente actual de la sehll o involucrar comandos tales como cd, que deben correr en la shell actual.
Por ejemplo, supongamos que existe una nueva versión del programa de correo en el sistema que se llama newmail, la cual deseamos utilizar en lugar del programa de correo estándar mail. Si en su fichero .cshrc emplea el comando de shell
alias mail newmail
la shell transformará una linea de entrada dada según la forma
mail bill
en una llamada de ejecución a newmail.
En concreto, supongamos ahora que deseamos el comando ls presente siempre los tamaños de los ficheros en su listado (o sea, que ls utilice siempre el argumento -s). Podemos usar
alias ls ls -s
o incluso
alias dir ls -s
creando una nueva sintaxis de comando llamada dir que ejecute un comando ls -s. Si decimos
dir ~bill
entonces la shell lo traducirá como
ls -s /mnt/bill
De esta forma, el mecanismo de alias puede usarse para proveer nombres cortos a comandos, para proveer argumentos por defecto, y para definir nuevos comandos cortos en relación a otros comandos. También es posible definir alias que contengan múltiples comandos o cañerías, mostrando donde se encuentran los argumentos del comando original para sustituirlos por medio de las facilidades del mecanismo de historia. Por tanto la definición
alias cd 'cd \!* ; Is '
haría un comando ls tras efectuado todo cambio de directorio con el comando cd. Apostrofamos entre caracteres ' la definición entera del alias a fin de impedir que se produzcan la mayoría de las substituciones, y el caracter : sea reconocido como un metacaracter. Aquí, el ! resulta anulado con una \ para impedir que sea interpretado al intruducir el comando de alias. El \!* sustituye aquí la lista argumental completa del comando cd previo al alias, sin dar un error si no tuviese argumentos. El ; que separa los comandos se usa aquí para indicar que un comando debe completarse, y luego el siguiente. De forma similar, la definición
alias whois 'grep \!^ /etc/passwd'
define un comando que busca su primer argumento en el fichero de contraseñas.
Cuidado: La shell actualmente lee el fichero .cshrc cada vez que inicia. Si dispone allí una cantidad excesiva de comandos, las shells tenderán a tener un inicio lento. Un mecanismo útil que guarde el ambiente de la shell luego de leer el fichero .cshrc y restaurarlo rápidamente se encuentra en desarrollo, pero por ahora debe intentar limitar la cantidad de alias que tiene a un número razonable… 10 o 15 es razonable; 50 o 60 causarán retrasos notables de arranque en las shells, y el sistema se volverá lento cuando ejecuta comandos desde el interior del editor u otros programas.
Mas redirecciones: >> y >&
Existen varias notaciones adicionales útiles para el usuario de terminal que no fueron explicadas aún.
Además de la salida estándar, los comandos también tienen una salida de diagnóstico que normalmente está dirigida al terminal, incluso cuando la salida estándar está redirigida a un fichero o a un caño. En ocasiones es deseable dirigir la salida de diagnóstico junto con la salida estándar. Por ejemplo, si desea redirigir la salida de un comando de larga ejecución a un fichero, y desea tener un registro de cualquier diagnóstico de error que produzca, puede ingresar
comando >& fichero
Aquí el >& le dice a la shell que redirija tanto la salida de diagnóstico como la salida estándar en fichero.
De manera similar, puede dar la orden comando
comando | & lpr
para redirigir tanto la salida estándar y la salida de diagnóstico a través de un caño al demonio de impresión lpr.
Finalmente, es posible usar la forma
comando >> fichero
para colocar la salida al final de un fichero existente.
Noclober
Existe una forma de comando
comando >&! fichero
Esta se usa cuando la variable noclobber está activada y fichero ya existe. Si noclobber está activada, entonces resultaría en error si fichero no existe. De otro modo la shell creará fichero si este no existe. La forma
comando >>! fichero
hará que no dé error si fichero es inexistente y la variable de shell noclobber está activada.
Trabajos; Segundo Plano, Primer Plano, o Suspendido
Al introducir uno o más comandos juntos siguiendo la forma de cañería (separados por |) o secuencia de comandos (separados por punto y coma ;), la shell genera un único trabajo (“job”), que consiste en dichos comandos unificados. Un comando aislado sin | o ; genera un trabajo mas simple. Usualmente, cada línea mecanografiada a la shell genera un trabajo. Algunas de las líneas que generan trabajos (uno por línea) son
sort < data ls -s | sort -n | head -5 mail harold
Si al final de los comandos se mecanografía el metacaracter &, entonces el trabajo correspondiente se inicia como un trabajo en segundo plano. Esto significa que la shell no aguardará su finalización, sino que quedará lista y a la espera de otro comando inmediato. Tal trabajo se ejecutará en el segundo plano, al mismo tiempo que los trabajos normales - llamados trabajos en primer plano - siguen siendo leídos y ejecutados por la shell de uno a la vez. Por lo tanto
du > uso_de_disco &
correrá el programa du, encargado de reportar el uso de disco de su directorio de trabajo (así como el de cualquier directorio por debajo de él), poner la salida en el fichero uso_de_disco y retornar inmediatamente con un prompt para eventual disposición de un comando ulterior (sin esperar a que du finalice). El programa du continuará su ejecución en el segundo plano hasta completarse, incluso aunque usted mientras tanto mecanografie y solicite ejecución de otros comandos. Justo antes del siguiente prompt, la shell presentará un mensaje cuando termine un trabajo en segundo plano, informando tal cosa. En el siguiente ejemplo, el trabajo du finalizó en cierto momento durante la ejecución del comando mail, y su finalización fue reportada justo antes de que el trabajo mail fuese finalizado.
% du > uso_de_disco & [1] 503 % mail bill ¿Cómo es posible saber cuando un trabajo en segundo plano ha finalizado? EOT [1] - Done du > uso_de_disco %
Ante una finalización anormal del trabajo, el mensaje Done podría verse reemplazado por algo distinto, como Killed. Si desea que le sean reportadas las finalizaciones de programas en segundo plano al mismo momento de ocurrir (posiblemente interrumpiendo la salida de terminal de otros trabajos en primer plano), puede establecer la variable notify. En el ejemplo anterior, esto podría implicar que el mensaje Done podría aparecer directamente en el medio de la redacción del correo a Bill. Los trabajos en segundo plano no resultan afectados por ninguna señal del teclado tales como las señales STOP, INTERRUPT, o QUIT mencionadas anteriormente.
La C shell registra los trabajos en una tabla de trabajos incorporada hasta su finalización. La shell toma nota de los nombres de comando, argumentos y el número de proceso de todos los comandos en el listado de trabajos, así como el directorio de trabajo donde se inició el trabajo. Cada trabajo de la tabla puede estar ejecutándose en primer plano (con la shell aguardando su finalización), corriendo en segundo plano, o suspendido. Sólo puede correr en el primer plano un trabajo a la vez, pero es posible contar con varios trabajos suspendidos o corriendo en segundo plano a la vez. Los números de trabajo siguen siendo los mismos hasta que el trabajo finalice, y luego son reutilizados.
Al iniciar la ejecución un trabajo en segundo plano por medio del sufijo &, antes que la shell le presente un prompt para ingresar un nuevo comando, le informará el número de trabajo - así como los números de proceso de todos sus comandos de nivel superior - . Por ejemplo,
% ls -s | sort -n > uso_de_disco & [2] 2034 2035 %
ejecuta el programa ls con la opción -s, entuba la salida resultante al programa sort con la opción -n que pone dicha salida en el fichero uso_de_disco. Debido a que el & aparece como sufijo al final de la línea, ambos programas se iniciaron conjuntamente en la forma de un trabajo en segundo plano. Tras iniciar el trabajo, la shell presentó el número de trabajo entre corchetes - [2] en este caso - seguido por el número de proceso de cada programa iniciado en el trabajo. Inmediatamente después la shell presenta un prompt para ingresar un eventual nuevo comando, dejando al trabajo ejecutándose en simultáneo.
Como se mencionó en la sección 1.8, los trabajos en primer plano se suspenden mecanografiando ^Z, lo cual envía una señal STOP al trabajo en ejecución en primer plano. Un trabajo en segundo plano puede ser suspendido utilizando el comando stop descripto adelante. Cuando los trabajos resultan suspendidos, su ejecución se detiene hasta ser iniciados nuevamente - ya sea en el primer o en el segundo plano. La shell nota cuando un trabajo se suspende e informa del hecho de manera bastante similar a los informes de finalización de trabajo en segundo plano. En el caso del trabajo en primer plano, esto guarda una apariencia similar a
% du > uso_de_disco ^Z Stopped %
cuando la shell nota que el programa du se ha detenido, presenta el mensaje Stopped. Cuando usamos el comando stop para detener los trabajos en segundo plano, se presenta
% sort uso_de_disco & [1] 2345 % stop %1 [1] + Stopped (signal) sort uso_de_disco %
Si necesitamos temporalmente conmutar entre lo que estábamos haciendo, puede sernos útil detener los trabajos en primer plano, ejecutar otros comandos, y retornar al trabajo suspendido. Asimismo, es posible detener los trabajos en primer plano y continuar su ejecución en la forma de trabajos en segundo plano por medio del comando bg. Esto le permitirá continuar un trabajo distinto, poniéndo el segundo plano en espera hasta que el trabajo en primer plano finalice. Por tanto
% du > uso_de_disco ^Z Stopped % bg [1] + uso_de_disco & %
inicia du en el primer plano, lo detiene antes de finalizar, luego lo continúa en segundo plano permitiendo la ejecución en primer plano de eventuales nuevos comandos. Esto se presenta especialmente útil cuando un trabajo en primer plano demanda más tiempo de ejecución que el previsto, por lo que usted hubiese deseado iniciarlo en segundo plano desde un principio.
Todos los comandos de control de trabajos pueden recibir un argumento que identifica el trabajo particular. Todos los argumentos de nombre de trabajo comienzan con el caracter %, si bien alguno de los comandos de control del trabajo también aceptan números de proceso (presentados por el comando ps). El trabajo por defecto (si no se le proveen argumentos) es llamado trabajo actual y es identificado por un + in la salida del comando jobs, el cual muestra cuáles son los trabajos que tiene. Cuando sólo hay un trabajo en ejecución o detenido en el segundo plano (el caso usual) este siempre será el trabajo actual, y por tanto no necesita argumentos. Si un trabajo ha sido detenido en el primer plano, se transforma en el trabajo actual y el trabajo actual existente se convierte en el trabajo previo. Cuando es dado, el argumento es tanto %- (que denota trabajo previo; %# donde el # es el número de trabajo; %pref (donde pref es algun prefijo único del nombre de comando y argumentos de uno de los trabajos; o ?% seguido por alguna cadena encontrada en solo uno de los trabajos.
Los tipos de comandos de trabajos de la tabla de trabajos, dando el número de trabajo, comandos, y status (Stopped or Running) de cada trabajo en segundo plano o trabajo suspendido. Con la opción -l los números de proceso también son presentados.
% du > uso_de_disco & [1] 3398 % ls -s | sort -n > mifichero & [2] 3405 % mail bill ^Z Stopped % jobs [1] - Running du > uso_de_disco [2] Running ls -s | sort -n > mifichero [3] + Stopped mail bill % fg %ls 15 -s | sort -n > mifichero % more mifichero
El comando fg ejecuta un trabajo suspendido o en segundo plano en el primer plano. Se usa para reiniciar un trabajo previamente suspendido, o cambiar un trabajo suspendido para que corra en el primer plano (permitiendo señales o entrada desde la terminal). En el caso anterior usamos fg para cambiar el trabajo ls desde el segundo plano al primer plano, desde que queríamos esperar a que terminara antes de mirar su fichero de salida. El comando bg corre un trabajo suspendido en el segundo plano. Usualmente se utiliza luego de detener el trabajo actual en ejecución en el primer plano con la señal STOP. La combinación de la señal STOP y el comando bg cambian el trabajo en primer plano a un trabajo en segundo plano. El comando stop suspende un trabajo en segundo plano.
El comando kill termina inmediatamente un trabajo en segundo plano o trabajo suspendido. Además de los trabajos, puede recibir como argumento números de procesos, tal como son presentados por ps. Por tanto, en el ejemplo anterior, al correr el comando du podría haber sido terminado por el comando
% kill %1 [1] Terminated du > uso_de_disco %
El comando notify (no es la variable notify mencionada anteriormente) indica que la terminación de un trabajo específico deberá ser informada inmediatamente al momento de su finalización, en lugar de aguardar el siguiente prompt.
Si un trabajo que corre en segundo plano intenta leer entrada del terminal, será automáticamente detenido. Cuando tal trabajo sea luego ejecutado en primer plano, se le podrá dar entrada al trabajo. Si lo desea, puede nuevamente enviar el trabajo al segundo plano hasta que éste solicite entrada nuevamente. Esto se ilustra en la secuencia siguiente, donde el comando s en el editor de texto puede llevar un tiempo largo.
% ed ficherogigante 120000 1,$s/estapalabra/otrapalabra ^Z Stopped % bg [1] ed ficherogigante & % ... algunos comandos en segundo plano [1] Stopped (tty input) ed archivazo % fg ed ficherogigante w 120000 q %
De manera que tras indicar el comando s, el trabajo ed fue detenido con ^Z y luego puesto en segundo plano usando bg. Algún tiempo después el comando s terminó, ed intentó leer otro comando y fue detenido pues los trabajos en segundo plano no pueden leer desde el terminal. El comando fg retorno el trabajo ed al primer plano, donde una vez mas pudo aceptar comandos desde el terminal.
El comando
stty tostop
provoca que todos los trabajos en segundo plano en su terminal se detengan cuando están por escribir salida al terminal. Se impedirá de esta manera que los mensajes de los trabajos en segundo plano interrumpan la salida de los trabajos en primer plano, y le permite tener un trabajo corriendo en segundo plano sin perder la salida de terminal. También puede utilizarse con programas interactivos que a menudo tienen períodos largos sin interacción. Por tanto, cada vez que una salida solicita más entrada del terminal, se detendrá antes de presentar el prompt de solicitud. Puede entonces correr en primer plano usando fg para proveer tal entrada, y si es necesario detenido y vuelto al segundo plano. Puede resultar útil insertar este comando stty en su fichero .login si es que no desea tener salida de los trabajos en segundo plano que le interrumpan su trabajo. También puede reducir la necesidad de redirigir la salida de los trabajos en segundo plano, y si la salida no es muy grande:
% stty tostop % wc ficherogigante & [1] 10387 % ed text ... algún tiempo después q [1] Stopped (tty output) wc ficherogigante % fg wc wc ficherogigante 13371 30123 302577 % stty - tostop
Por lo tanto, tras algún tiempo de ejecutar el comando wc (que cuenta líneas, palabras y caracteres de un fichero), tenemos una línea de salida. Cuando intentamos escribir esto al terminal, se detuvo. Al reiniciarlo en el primer plano, nos permitido escribir en el terminal exactamente cuando estábamos listos para observar esta salida. Cuando no estén en primer plano, aquellos programas que intentan cambiar el modo del terminal también se bloquearán, ya sea que tostop esté establecido o no (ya que sería muy inconveniente que un programa en segundo plano quiera cambiar el estado del terminal).
Como los comandos de trabajos sólo presentan trabajos iniciados en la shell de ejecución actual, no saben nada sobre los trabajos en segundo plano iniciados en otras sesiones de login, o dentro de los ficheros de la shell. En este caso puede usarse ps para descubrir los trabajos en segundo plano no iniciados durante la instancia actual de shell.
Directorios de Trabajo
Comandos Incorporados útiles
Ahora ofrecemos algunos pocos comandos útiles incorporados en la shell, y describimos como se usan.
El comando alias descripto arriba se usa para asignar nuevos alias y para mostrar los alias existentes. Si argumentos, presenta los alias existentes. También puede dársele sólo un argumento tal como
alias ls
El comando echo imprime sus argumentos. A menudo es usado en guiones de shell o como un comando interactivo para veer qué expansiones de nombre de fichero producirá.
El comando history mostrará los contenidos de su listado de historial. Los números dados a los eventos del historial pueden usarse para referencia eventos anteriores que son difíciles de referenciar utilizando los mecanismos contextuales introducidos anteriormente. Existe también una variable de shell denominada prompt.
Al colocar un caracter ! en su valor, la shell substituirá el número del comando actual con el del listado de historial. Puede usar este número para referir a este comando en una subsitución de historia. Por lo tanto, podría
set prompt='\!% '
Tenga presente que el ! debe ser anulado aquí incluso entre caracteres de apoóstrofo '.
El comando limit se use para restringir el uso de recursos de cómputo. Sin argumentos, presentará las limitaciones actuales:
cputime unlimited filesize unlimited datasize 5616 kbytes stacksize 512 kbytes coredumpsize unlimited
Los límites pueden establecerse, de esta manera:
limit coredumpsize 128k
Funcionarán la mayoría de las abreviaciones razonables; vea el man de csh para más detalles.
El comando logout puede utilizarse para terminar una sesión de shell que tiene establecido la variable ignoreeof.
El comando rehash provoca que la shell recompute una tabla de localización de comandos. Esto es necesario si se agregó un comando a un directorio en la ruta de búsqueda path de la shell actual, y se desea que la shell proceda a encontrarla, de otro modo el algoritmo de detección podría decirle a la shell que el comando no se encontraba en los comandos indicados cuando la tabla de hash fue computada originalmente.
El comando repeat puede utillizarse para repetir un comando varias veces. Por tanto, para realizar cinco copias del fichero uno hasta el fichero cinco, podría hacer
repeat 5 cat uno >> cinco
El comando setenv puede usarse para establecer variables de ambiente. Por tanto
setenv TERM=adm3a
establecerá el valor de la variable de ambiente TERM a la cadena adm3a.
Un programa de usuario llamado printenv existe, que imprimirá el ambiente. Podría mostrar
% printenv HOME=/usr/bill SHELL=/bin/csh PATH=:/usr/ucb:/bin:/usr/bin:/usr/local TERM=adm3a USER=bill %
El comando source puede usarse para forzar a la shell actual a leer comandos desde un fichero. Por tanto
source .cshrc
puede usarse luego de editar un cambio en el fichero .cshrc el cual desea que surta efecto antes de la siguiente vez que inicie sesión.
El comando time puede usarse para cronometrar un comando, sin emportar cuántos ciclos de computadora requiera. Por tanto
% time cp /etc/rc /usr/bill/rc 0.0u 0.1s 0:01 8% 2+lk 3+2io 1pf+0w % time wc /etc/rc /usr/bill/rc 52 178 1347 /etc/rc 52 178 1347 /usr/bill/rc 104 356 2694 total 0.1u 0.1s 0:00 13% 3+3k 5+3io 7pf+Ow %
indica que el comando cp usó una cantidad de tiempo de usuario negligible (u) y aproximadamente 1/10 del tiempo de sistema (s); el tiempo transcurrido fue de 1 segundo (0:01). Hubo un uso promedio de memoria de 2k bytes de espacio de programas, y 1k bytes de espacio de datos sobre el tiempo de CPU involucrado (2+1k), el programa hizo tres lecturas de disco y dos escrituras (3+2io), y tomó un paginado y no hizo uso de memoria de intercambio (1pf+0w). El comando de conteo de palabras wc por otro lado utilizó un décimo de segundos de tiempo de usuario (0.1), menos de un segundo del tiempo transcurrido en el sistema. El porcentale de 13% indica que durante dicho período el comando activo wc usó un 13 porciento de los ciclos de computadora disponibles ne la máquina.
Los comandos unalias y unset pueden usarse para remover alias y definiciones de variable de la shell, y unsetenv quita variables del ambiente.
¿Qué mas?
Esto concluye la discusión básica de la shell para los usuarios de terminal. Existen más funcionalidades de la shell que las explicadas aquí, y todas las funcionalidades de la shell se tratan en las manpages. Una funcionalidad útil que se discutirá luego es el comando incorporado foreach que puede utilizarse para ejecutar la misma secuencia de comandos con una cantidad de argumentos distintos.
Si usted desea utilizar UNIX, debería revisar el resto de este documento y las manpages de la shell para familiarizarse con las otras funcionalidades que tiene disponibles.
3. Estructuras de Control de Shell y Guiones de Comandos
Introducción
Es posible colocar comandos en ficheros y hacer que la shell se involucre leyendo y ejecutando los comandos que contienen tales ficheros, a los cuales se les llamará script de shell. Detallamos aquí aquellas funcionalidades de la shell que resutan útiles a quienes escriben tales scripts.
Make
Es importante recalcar primero para qué son útiles los guiones de shell. Existe un programa llamado make que es muy útil para mantener un grupo de ficheros relacionados, desarrollando un conjunto de operaciones sobre ellos. Por ejemplo, un gran programa consistente en uno o mas ficheros puede tener sus dependencias descriptas en un makefile, un fichero que guarda definiciones de comandos utilizados para crear esos ficheros diferentes cuando las definiciones cambian. Estas definiciones facilitan los medios para imprimir listados, limpiar el directorio en el cual residen los programas, instalar el programas resultante colocando mas apropiadamente los ficheros definidos en este makefile. Tal formato es superior y preferible a manejar un grupo de procedimientos de shell afrotar dicha tarea.
De la misma manera, al realizar preparaciones documentales puede crearse un makefile para definir cómo crear las versiones diferentes del documento y cuáles opciones de rooff o troff son adecuadas para su utilización.
Invocación y variable argv
Puede intepretar un guion de C Shell diciendo
% csh guion ...
donde guion es el nombre del fichero que contiene un grupo de comandos de Csh y … se reemplaza por una secuencia de argumentos. La shell coloca dichos argumentos en la variable argv y luego comienza a leer los comandos del guion. Estos parámetros están puestos a disponibilidad a través de los mismos mecanismos que se usan para referenciar cualquier otra variable de shell.
Si hace el fichero guion ejecutable haciendo
chmod 755 guion
y coloca un comentario de shell, al comienzo del guion de shell (ej, comienza el fichero con un caracter de #), seguido de /bin/csh, esta automáticamente será invocada para ejecutar el guion cuando ingrese
guion
Si el fichero no comienza con # entonces se utilizará la shell estándar /bin/sh para ejecutarlo. Esto le permitirá convertir sus guiones más antiguos para interpretarlos con csh según lo crea conveniente.
Sustitución de Variables
Una vez que cada línea de entrada es dividida en palabras y se realizan las substituciones de historia, se desmenuza la línea de entrada en comandos unívocos. Antes de ejecutar cada comando, en las palabras se lleva a cabo un mecanismo conocido como sustitución de variables. Indicado por el caracter $, esta sustitución reemplaza los nombres de las variables por sus valores. Por tanto el
echo Sargv
colocado en un guion de comandos, provocará que el valor de la variable argv sea presentada como salida del eco del guion de shell. Si argv no se encuentra establecida en este momento, provocará un error.
Están previstas varias notaciones de acceso a componentes y atributos de variables. La notación
$?nombre
se expande a 1 si nombre está establecida (set), o en 0 si no está establecida (unset). Este es el mecanismo fundamental para evaluar si las variables particulares han sido asignadas a valores. Todas las demás formas de referencia a variables no definidas provocarán errores.
La notación
$#nombre
se expande al número de elementos en la variable nombre. Por tanto
% set argv=(a b c) % echo $?argv 1 % echo $#argv 3 % unset argv % echo $?argv 0 % echo $argv Undefined variable: argv. %
También es posible acceder a componentes de una variable que cuenta de varios valores. POr tanto
$argv[l]
da el primer componente de argv o - en el ejemplo anterior - a. De igual forma
$argv [$#argv]
dará c, mientras que
$argv[1-2]
dará a b. Otras notaciones útiles en guiones de shell son
$n
Donde n es un entero que oficia de abreviación de
$argv[n]
el n° parámetro, y
''$*''
que as la abreviación de
$argv
La forma
$$
expande al número de proceso de la shell actual. Como dicho número de proceso es único en el sistema, bien puede utilizarse para generar nombres de fichero temporales únicos. La forma
$<
es bastante especial y es reemplazada por la siguiente línea de entrada, a ser leída desde la entrada estándar de la shell (no del guion que estaba siendo leído). Esto resulta muy útil para escribir guiones de shell interactivos, que leen comandos de la terminal, o incluso escribir guiones de shell que actúan como un filtro, capaz de leer líneas de su fichero de entrada. Por tanto, la secuencia
echo '¿si o no?\c' set r- ($<)
Presentará la solicitud ¿si o no?, sin presentar una nueva línea, y luego leerá una respuesta dada, colocándole como variable r. En este caso $#r será 0 si se mecanografía tanto una línea en blanco o un fin-de-fichero (^D).
Debemos llamar la atención de una diferencia menor entre $n y $argv[n]. La forma $argv[n] dará un error si n no se encuentra en el rango 1-$#argv, mientras que $n nunca dará un error de suscripto fuera de rango. Esto se hace para retener compatibilidad con la manera con la cual los shells mas antiguos manejaban los parámetros.
Otro punto importante es que nunca es un error dar un subrango en la forma de n-; si hay menos de n componentes de una variable dada entonces no se substituye palabra alguna. Un rango en la forma m-n de la misma forma devolverá un vector vacío sin dar error, toda vez que m exceda el número de elementos de la variable dada, provisto que el suscripto n se encuentre dentro del rango.
Expresiones
Para poder construir guiones de shell interesantes, debe ser posible evaluar expresiones en la shell basadas en los valores de variables. De hecho, todas las operaciones aritméticas del lenguaje C están disponibles en la shell con la misma precedencia que tienen en el lenguaje C. En particular, las operaciones == y != comparan cadenas y los operadores &&, y || implementan las operaciones de lógica de Boole AND/OR. Los operadores especiales =' y !' son similares a == y !=., excepto que la cadena en el lado derecho puede tener caracteres de coincidencia de patrones como *, ?, o [], y la evaluación consistirá en si la cadena de la izquierda coincide con el patrón de la derecha.
LKa shell también permite solicitudes de ficheros según la forma
-? filename
donde ? es reemplazado por una cifra numérica de un caracteres simples. Por ejemplo, la expresión primitiva
-e nombre_fichero
informará si el fichero nombre_fichero existe. Otras primitivas evalúan por acceso de lectura, escritura y ejecución de un fichero., si este es un directorio, o si tiene longitud no cero.
Es posible evaluar si un comando termina normalmente, por una primitiva de la forma de { comando }, que recorna verdadero (ej, 1) si el comando tiene éxito en salir normalmente con status 0 de salida, o 0 si el comando termina anormalmente o con un status de salida distinto a cero. De requerirse mayor información detallada sobre el status de ejecución de un comando, puede ser ejecutado con la variable $status examinada en el siguiente comando. Como $status está establecida por todos los comandos, en muy demostrativa. Puede ser salvada si es inconveniente de usarla sólo una sola vez inmediatamente por el comando que sigue.
Si desea un listado completo de componentes de expresión dispoible, observe dicha sección del manual de la shell.
Ejemplo de guion de shell
A continuación, un guion de shell de ejemplo, que hace uso de mecanismo de expresión de la shell y alguna de sus estructuras de control
% cat copyc # # Copyc copia los programas en la lista especificada # al directorio ~/respaldo si difieren de los ficheros # que ya están en ~/respaldo # set noglob foreach i (Sargv) if ($i !* *.c) continue # no es un fichero .c de modo que no hace nada if (! -r ~/respaldo/Si:t) then echo $i:t no en respaldo ... no cp\'ado continue endif cmp -s $i ~/respaldo/$i:t # para establecer $status if ($status ! = 0) then echo nuevo respaldo de $i cp $i ~/respaldo/Si:t endif end
Este guion hace uso del comando foreach, que provoca que la C Shell ejecute los comandos dispuestos entre el foreach y su correspondiente end para cada uno de los valores dados entre la ( y la ) con la variable nombrada, en este caso i establecida en valores sucesivos de la lista. Dentro de este bucle podemos usar el comando break para detener la ejecución del bucle y continuar para terminar prematuramente una iteración y comenzar con la siguiente. Luego del bucle foreach la variable de iteración (i en este caso) tendrá el valor de la última iteración.
Establecemos la variable noglob aquí para impedir que la expansión de nombre de ficheros de los miembros de argv. Esto es generalmente una buena idea si los argumentos de un guion de shell son nombres de ficheros que han sido ya expandidos, o si los argumentos podrían contener metacaracteres de expansión de nombres de fichero. También es posible citar cada uso de una variable de expansión $, pero esto es más difícil y menos confiable.
La otra estructura de control empleada aquí es una declaración de la forma
if ( expresión ) then comando ... endif
La colocación de las palabras claves aquí utilizada no es flexible, debido a la actual implementación de la shell (ver limitaciones.
La shell tiene otra forma de la declaración if que guarda la forma
if ( expresión ) comando
Que si es una línea muy larga, puede ser escrita
if ( expresion ) \ comando
Aquí anulamos la nueva línea por estética. El comando no debe involucrar un |, & o ;, y no debe ser otro comando de control. La segunda forma, requiere que la \ final preceda inmedatamente al fin-de-linea (o sea, no de debe dejarse espacio).
La declaración if más general anterior también admite la secuencia o pares else-if seguidos por un único else y un endif, por ejemplo
if ( expression ) then comandos else If (expression ) then comandos else comandos endif
Otro mecanismo importante usado en guiones de shell es el modificador :. Podemos usar el modificar :r aquí para extraer una raíz de un nombre de fichero, o :e para extraer la extensión. Por tanto, si la variable i tiene el valor /mnt/foo.bar, entonces
% echo $i $i:r Si:e /mnt/foo.bar /mnt/foo bar %
muestra como el modificador :r quita el .bar final de la cadena, y el modificador :e deja solo el bar. Otros modificadores quitan el último componente de un nombre de ruta, dejando la cabeza :h o dejando todo a excepción del último componente del nombre de ruta dejando la cola :t. Estos modificadores son descriptos al completo en las manpages de csh, en el manual del programador. Es también posible usar el mecanismo de sustitución de comandos descriptos en la siguiente sección para desarrollar modificaciones en cadenas y luego reingresar el ambiente de la shell. Como cada uso de este mecanismo involucra la creación de un nuevo proceso, es mucho más costoso en términos computacionales que usar la modificación :. Finalmnet,e debemos notar que el caracter # introduce léxicamente un comentario de shell en los guiones de shell (por no desde la terminal). Todos los caracteres subsecuentes en la línea de entrada a posterior del # resultan descartados por la shell. Este caracter puede ser citado usando * o \ para ponerlo en una palabra argumento.
Limitaciones
Las siguiente dos formas no son aceptables por C shell:
if ( expresión ) # No funciona! tben comando ... endif
y
if ( expresión ) tben comando endif # No funciona
También es importante notar que la implementación de la C shell limita el número de modificadores : en una sustitución $ a solo 1. Por tanto
% echo $i $i:h:t /a/b/c /a/b:t %
no hace lo que uno esperaría.
Otras estructuras de control
La C shell también tiene estructuras de control while y switch similares a las del lenguaje C. Estas guardan las formas
while ( expresión ) comandos end
y
switch ( palabra ) case str1: comandos breaksw ...
case stm:
comandos
breaksw
default:
comandos
breaksw
endsw
Para mayores detalles, consulte la sección del manual de csh. Los programadores de C deben notar que usamos breakslt para salir de un switch, ientras que break sale de un bucle while o foreach. Un error común de cometer en los giones de csh es usar los conmutadores break en lugar de breaksw.
Finalmente, csh permite declaraciones goto con etiquetas que son similares alas de C. Ejemplo:
bucle:
comandos
goto bucle
Suplir entrada a comandos
Los comandos ejecutados desde guiones de ghell reciben por defecto la entrada estándar de la shell que corre el guion. Esto es distinto a shells precias que corren en UNIX. Esto permite a los guiones de C shell de participar completamente en tuberías, pero obligan a realizar notación extra para los comandoos que deben tomar datos en línea.
Por lo tanto necesitamos una metanotación para proveer datos en línea a los comandos situados en guiones de C shell. Como ejemplo, considere este guion que corre el editor para borrar los caracteres iniciales en blanco desde las líneas en cada fichero argumento.
% cat deblanqueador.sh # deblanqueador.sh - Quita los caracteres en blanco al inicio de una línea foreach i (Sargv) ed - Si << 'EOF' 1,$s/^[ ]*// w q 'EOF' end %
La notación << 'EOF' significa que la entrada estándar para el comando ed debe provenir del texto en el fichero de guion de shell en sí, hasta la siguiente linea, lo que literalmente consiste en “'EOF'”. El hecho de que EOF se encuentre apostrofado (citado) provoca que la shell no sustituya variables en las líneas intervinientes. En general, si alguna parte de la palabra que sigue a « - la cual la shell usa para terminar el texto a ser dado al comando - se cita, entonces se anula la subsitución de tales substituciones. En este caso, como en nuestro guion de edición hemos utilizado la forma 1,$, debemos asegurar que este $ no sufra sustitución como variable. Podríamos haberlo asegurado también por medio de preceder dicha $ con un caracter de \. Por ejemplo:
1,\$s/^[ ]*//
sin embargo, citar el terminador 'EOF' es una manera más confiable de lograr lo mismo.
Atrapando interrupciones
¿Qué mas?
4. Otras funcionalidades de la shell menos utilizadas
Bucles en la terminal; variables como vectores
Llaves {...} en expansión de argumentos
Otros detalles no cubiertos
Caracteres Especiales
La siguiente tabla lista los caracteres especiales de csh y el sistema UNIX.
Metacaracteres sintácticos
| Metacaracter sintáctico | Sintáctica |
|---|---|
; | separa comandos para ejecutarlos secuencialmente |
| | separa comandos en un caño |
() | entre paréntesis de expresiones y valores de variables |
& | continúa ejecutando los siguientes comandos sin esperar completar la ejecución |
Metacaracteresa de nombre de fichero
| Metacaracter de nombre de fichero | Acción |
|---|---|
/ | separa los componentes de una ruta de fichero |
? | expansión de caracter coincidente con cualquier caracter único |
* | expansión de caracter coincidente con cualquier secuencia de caracteres |
[] | expansión de secuencia coincidente con cualquier caracter único de un conjunto |
~ | usado al comienzo del nombre de fichero para indicar directorios $home |
{} | usado para especificar grupos de argumentos con partes comunes |
Metacaracteres de citado
| Metacaracter de citado | Acción |
|---|---|
/ | impide el metasignificado del siguiente caracter único |
' | impide el metasignificado de un grupo de caracteres |
* | como ' pero permite variables y expanisión de comandos |
Metacaracteres de entrada y salida
| Metacaracter de redirección | Redireccionado |
|---|---|
< | indica redirección de entrada |
> | indica redirección de salida |
Expansión/substitución de metacaracteres
| Metacaracter | Acción |
|---|---|
$ | indica substitución de variables |
! | indica subsitución de historial |
: | precede modificadores de sustitución |
^ | usado en formas especiales de sustitución de historial |
` | indica sustitución de comandos |
Otros metacaracteres
| Metacaracter | Resultado | ||
|---|---|---|---|
$ | comineza garabateo de nombres de fichero; indica comentarios de shell | | |
! | opción de refijado (flag) argumentos a comandos. | ||
| prefija especificaciones de nombre de trabajo |
