Practicas de Sistemas Telemáticos Introducción al Sistema Operativo LINUX Guión 1 1. INTRODUCCIÓN Linux es un sistema operativo diseñado a partir de los sistemas operativos UNIX y desarrollado por Linus Benedict Torvald. UNIX fue el primer sistema operativo que apareció en el año 1969 en los laboratorios de la empresa AT&T desarrollado por Ken Thompson. En el momento en el que se desarrolló UNIX, no existía el concepto de "ordenador personal" sino que las computadoras de entonces se encontraban en las grandes empresas, pues eran modelos muy voluminosos y, sobre todo, caros. A principios de los años 90, fue cuando Linus, desarrolló Minix, que era una versión educativa de UNIX capaz de ser ejecutada en ordenadores personales. A partir de esta versión educativa de UNIX, se desarrolló el sistema operativo Linux. A mediados de los años 60 las empresas MIT, AT&T y General Electric se juntaron para realizar un gran proyecto, se trataba de hacer un SO de gran potencia al que denominaron MULTICS. El proyecto fue un fracaso pero uno de los programadores del MIT que habría trabajado en el proyecto, Ken Thompson, y un grupo de colaboradores decidieron escribir una versión miniatura de MULTICS. Unos de los compañeros de Ken, Brian Kernigham, en una reunión de equipo bromeando llamó al sistema de Ken Thompson UNICS. UNICS fue un gran éxito y Ken decidió que UNIX era un nombre más atractivo que UNICS. Un famoso artículo del año 1974 que describía UNIX atrajo la atención de las universidades que solicitaron el código fuente para estudiarlo y explicarlo en las aulas. Muy pronto, UNIX logro una gran aceptación en la comunidad científica y el interés por este sistema operativo comenzó a extenderse. A partir de este momento comienza una verdadera avalancha de versiones del sistema, lo que primero en un principio empezó como un proyecto de investigación se convirtió más tarde en un gran negocio. Las más importantes de todas las versiones de UNIX fueron la BSD, de la Universidad de California en Berkeley, que contenía una serie de mejoras que hicieron a UNIX un sistema operativo más amigable, y la System V. Esta última surgió de la fusión de las respectivas versiones de UNIX de AT&T Bell Laboratories, los creadores del sistema, y Sun Microsystems. Actualmente el System V es considerado el estándar de UNIX, ya que toda la industria ha sido agrupada entorno a él. A pesar del éxito comercial de UNIX y de su aceptación como sistema operativo, el código fuente de UNIX no podía ser explicado en aulas universitarias, de modo que el desarrollo de sistemas operativos volvía a ser una ciencia restringida a un reducido grupo de empresas y personas. Ante esta situación, el profesor Andrew Tanenbaum, de la Universidad de Vrije, en Amsterdam, decidió imitar a Ken Thompson cuando escribió el código de UNIX basándose en MULTICS, e inspirándose en UNIX llevó a cabo un nuevo sistema operativo mucho mas reducido, al que llamó MINIX (de Mini-UNIX). MINIX había sido desarrollado en una IBM PC y, sin embargo ofrecía las mismas llamadas al sistema que UNIX V7. Tanenbaum hizo público el código de MINIX, y su texto aún se usa en la mayoría de las universidades del planeta para enseñar las bases del diseño de sistemas operativos. En 1990, Linus Torvals, un estudiante de 23 años de la Universidad de Helsinki, en Finlandia, comenzó a desarrollar, como hobby, un proyecto basado en el MINIX de Andrew Tanenbaum. Quería llevar a cabo, sobre una computadora con procesador Intel 80386, un sistema operativo tipo UNIX que ofreciese más capacidades que el limitado MINIX, que solo se usaba para enseñar una cierta filosofía de diseño. Quería aprovechar la arquitectura de 32 bits, las propiedades de conmutación de tareas que incorporaba la interfaz en modo protegido del 80386 y eliminar las barreras del direccionamiento de memoria. Linus empezó escribiendo el núcleo del proyecto en ensamblador, y luego comenzó a añadir código en C, lo cual incrementó la velocidad de desarrollo, e hizo que empezara a tomarse en serio su idea de hacer un "MINIX mejor que MINIX". La primera versión, la 0.01 no tenía driver de disquete, y ni siquiera la dio a conocer. Llevaba incorporado un pequeño sistema de archivos y un driver de disco con mucho errores... pero funcionaba. En octubre de 1991, anuncio la primera versión "oficial" de LINUX, la 0.02, que ya era capaz de ejecutar el SHELL bash y el compilador gcc de GNU. 2. INTRODUCCIÓN AL SISTEMA DE FICHEROS DE UNIX El sistema de ficheros de un sistema operativo UNIX tiene las siguientes características: - Estructura jerárquica ( estructura en árbol) - Tratamiento consistente de los datos - Posibilidad de aumento de tamaño dinámico de los ficheros - Protección de los datos - Tratamiento de los dispositivos como ficheros Estructura jerárquica (estructura en árbol) En cuanto a la estructura jerárquica del sistema de ficheros podemos establecer un árbol de directorios empezando por un nodo raíz, denominado “root” y cuyo símbolo es “/”. Este es el directorio padre de todos los directorios, a partir del podremos ir creando hijos de este sucesivamente: / grupo3 grupo1 grupo2 datos personal Cada hoja dentro de este árbol que no sea terminal (, es decir, que tenga descendientes) es un directorio y los nodos hoja del árbol pueden ser ficheros o directorios. Ejemplo: En el árbol de la figura de arriba el nodo “grupo1” es un directorio porque tiene dos descendientes (“datos” y “personal”). A su vez “datos” puede ser un fichero o un directorio (luego veremos como todos los directorios son ficheros, pero no todos los ficheros son directorios). Para especificar la ubicación (path) de un fichero deberemos empezar escribiendo el directorio raíz y luego sus antecesores separados por el carácter “/”. Ejemplo: El path del fichero datos seria: El nodo raíz = / + El 1er ancestro = grupo1 + “/” + Nombre de fichero = datos PATH = /grupo1/datos También podemos especificar la ubicación de un fichero en función de nuestra ubicación actual, por ejemplo, si nosotros estamos en el directorio “grupo1” y queremos acceder al directorio “personal” no tenemos que especificar todo el camino hasta personal y podemos considerar que nuestra posición actual es la posición raíz de modo que: Camino total a personal: /grupo1/personal Camino total Posición actual: /grupo1/ Camino a personal desde posición actual: personal Tratamiento consistente de los datos El sistema operativo trata los datos almacenados en el sistema de ficheros de forma consistente. El SO internamente ve los datos de todos los ficheros como una secuencia de bytes sin un formato definido. Por lo que la sintaxis para el acceso a los datos es la misma independientemente del formato en el que los datos serán usados posteriormente por una aplicación. Posibilidad de aumento de tamaño dinámico de los ficheros Un fichero podrá variar de tamaño sin tener problemas de reserva de espacio en el disco. Protección de los datos Cada fichero tiene asociados una serie de permisos que nos van a permitir especificar los privilegios para la lectura, escritura y ejecución. Podremos especificar estos permisos para un grupo determinado, para el propietario del fichero y para todos los demás usuarios. Por ejemplo podremos configurar los permisos de forma que todos los usuarios puedan leerlo, que los del grupo “blanco” puedan leerlo y escribir sobre él y que solo el propietario del fichero pueda leerlo, modificarlo y ejecutarlo: Grupo “Blanco”: Leer, Escribir Propietario: Leer, Escribir y Ejecutar fichero Todos: Leer Tratamiento de los dispositivos como ficheros En UNIX, un disco, por ejemplo, no es accedido mediante una unidad especial, sino como un directorio. Cada dispositivo es considerado como un fichero (directorio). Podremos establecer los mismos privilegios que establecemos para un fichero, para un dispositivo. Estructura global del sistema de ficheros A continuación se muestran los componentes del sistema de ficheros, posteriormente analizaremos uno a uno: Bloque de arranque (Boot Block) Superbloque Lista de I-nodos Bloques de datos 2.1 Representación interna de los ficheros 2.1.1. Concepto de I –Nodo Un I-Nodo es la representación interna de un fichero, que va a contener información sobre este fichero. Este termino viene de las palabras “Index Node”. Un I-nodo reside en disco, pero cuando un fichero debe ser manipulado, el sistema operativo copia el I-nodo que esta en el disco y trabaja con una copia interna. Tanto el I-nodo residente en disco como la copia interna que posee el Sistema Operativo tienen los siguientes campos: 1) Identificador del usuario propietario del fichero. Esta identificación puede ser a nivel de usuario y a nivel de grupo. 2) Tipo de fichero. Pueden ser simples ficheros, directorios y FIFO (pipes) 3) Permisos de acceso al fichero. Podemos establecer permisos a tres niveles: - A nivel de usuario - A nivel de grupo - A nivel de otros usuarios En cada nivel podremos configurar, independientemente del nivel, los permisos de lectura, escritura y ejecución... En caso de que estemos hablando de un directorio, el permiso de ejecución se corresponde con la posibilidad de poder explorar el directorio en busca de un nombre de fichero. 4) Tiempo de acceso al fichero. Se almacena la fecha y hora en la que el fichero fue accedido por última vez, de cuando fue modificado por última vez y de cuando el I-nodo se escribió en disco por última vez. 5) Numero de enlaces a ese fichero 6) Tabla con las direcciones de los bloques de datos del fichero. Aunque lógicamente, un fichero es una secuencia contigua de bytes, el sistema operativo lo almacena en disco dividiéndolo en bloques de datos, de los cuales tiene que conocer su posición en el disco. 7) Tamaño del fichero. Además de todos estos campos, la copia interna que realizada el kernel del sistema operativo tiene los siguientes campos: 8) El estado de la copia interna del I-nodo. Pudiendo ser: - El I-nodo esta bloqueado - Un proceso esta esperando a que el I.-nodo sea liberado - La copia interna del I-nodo es distinta de el I-nodo residente en disco (se ha modificado después copiarla del disco) - La copia interna del fichero es distinta de el fichero residente en disco (se han modificado los datos del fichero) - El fichero es un punto de montaje. 9) El numero lógico del dispositivo que contiene al sistema de ficheros donde se encuentra el I-nodo (p.ej. si esta en el disco duro o en el CD) 10) El número de I-nodo. Este se corresponde con la posición del I-nodo en el vector de I-nodos que se encuentran almacenados en disco. 11) Punteros a otras copias internas de I-nodos.(para localizar I-nodos internos libres) 12) Un contador para el numero de instancias del fichero que están activas ( 2.1.2 Estructura de un fichero Como hemos visto en el punto anterior, el I-nodo posee una tabla con las direcciones de los bloques de datos en disco. Gracias a esta tabla vamos a poder localizar en el disco los bloques de datos dispersos por todo el disco. Como cada bloque de disco se puede direccionar, la tabla con estas direcciones va a contener una dirección de bloque de disco en cada entrada. Aunque esta estrategia de almacenamiento pueda parecer un poco mas compleja, que por ejemplo, almacenar la dirección del bloque donde empieza el fichero y que desde esa dirección hasta el tamaño del fichero este contenido el fichero. A priori esta solución es muy cómoda pero no nos permite que el fichero crezca de tamaño ya que si creciera sobrescribiría a otro fichero y en caso de disminuir de tamaño se quedarían bloques libres y habría que defragmentar el disco constantemente. Para evitar que esta tabla alcance un tamaño desmesurado, se utiliza lo que se conoce como “direccionamiento indirecto”. En esta técnica vamos a tener las primeras entradas de la tabla apuntando a direcciones de bloque, es decir, hacen un direccionamiento directo al disco. Tras estas entradas encontramos otras que en vez de apuntar a bloques de disco de datos, apuntan a un bloque de datos que no contiene datos pertenecientes a ese archivo sino que contiene una lista con direcciones de bloques de datos de ese fichero. Esto sería un direccionamiento simple indirecto, del mismo modo podemos proceder y hacer doble indirecto y triple... pudiendo alcanzar así longitudes de fichero suficientemente grandes. Tabla de direcciones del I-nodo Bloques de datos de disco Bloque 0 Bloque 1 Dir. directo Bloque 5 ..... Dir. Simple indirecto Bloque Dir. Doble indirecto Bloque 2.1.3 Estructura de un directorio Un directorio es un fichero cuyos datos son una secuencia de entradas, consistiendo cada una de ellas en un número de I-nodo y el nombre de fichero que apunta a ese Inodo dentro de ese directorio: Byte Offset Numero de I-nodo (2 Nombre de fichero bytes) 0 83 . 16 2 .. 32 456 Datos 48 123 Personal Todos los directorios contienen los nombres de fichero “.” Y “..”, estos dos ficheros representan al directorio padre y al mismo directorio. El acceso a los directorios se realiza de la misma forma que con los archivos normales. Dependiendo de una distribución u otra, podremos encontrar unos directorios distintos, pero en general, todas las distribuciones poseen estos directorios en común: /etc Directorio administrativo /bin Directorio con programas ejecutables del sistema /dev Directorio de dispositivos /tmp Directorio para archivos temporales /usr Directorio de usuarios /usr/bin Directorio de programas ejecutables de aplicación /var Directorio variable Cuando entramos al sistema, se nos asigna un directorio por defecto, es el directorio de trabajo actual. Por norma general, el nombre de este directorio coincide con el nombre de usuario con el que hayamos entrado en el sistema y se situará en el directorio “home” del usuario, este directorio se suele encontrar dentro del directorio “/usr” y su nombre suele coincidir con el username, aunque puede ser personalizado para que nuestro directorio “home” pueda ser otro. 2.1.4 El SuperBloque El superbloque es una estructura que contiene la información sobre la cual nos vamos a valer para poder asignar I-nodos a los ficheros nuevos que creemos. En el superbloque tenemos los siguientes campos: - El tamaño del sistema de ficheros - El numero de bloques de datos libres en el disco - Una lista con los bloques libres - El índice dentro de la lista de bloques libres del siguiente bloque disponible - El tamaño de la lista de I-nodos - El numero de I-nodos libres - Una lista con los I-nodos libres - El índice del siguiente I-nodo disponible dentro de la lista de I-nodos Del mismo modo que con los I-nodos, el kernel del sistema operativo mantiene una copia del superbloque interna que actualiza y escribe en el disco cuando es modificada. 2.1.5 Otros tipos de ficheros Ficheros fifo: ficheros que sirven para transito de datos únicamente (p.ej. comunicación entre dos procesos) solo se pueden obtener los datos en la misma secuencia en la que fueron escritos (primero en entrar, primero en salir). Ficheros de dispositivos: Son los ficheros especiales que representan a los dispositivos. 3. LOS INTÉRPRETES DE ÓRDENES, SHELLS Al igual que UNIX, Linux suministra un intérprete de órdenes construido como un programa más de usuario. Esto tiene la enorme ventaja de que podemos cambiar de interprete de ordenes según nuestras necesidades o preferencias. El shell es un programa que básicamente realiza las siguientes tareas: For(;;){ Imprime indicador del sistema Obtiene línea de órdenes Analiza la línea de órdenes Prepara entorno según aparece en la línea de órdenes Crea los procesos necesarios If (es un proceso hijo) Ejecuta orden Else Esperar a que finalice el hijo } Cada shell, además de ejecutar las órdenes de UNIX, tiene sus propias órdenes y variables, por lo que es también un lenguaje de programación. Existen diferentes shells cada uno con una serie de características (Bourne shell (sh), C Shell (csh), T-C shell (cts.), Korn shell (ksh), Bourne Again shell (bash)). Las diferencias entre los distintos shells residen en la sintaxis que soportan a la hora de escribir scripts o secuencias de instrucciones. 3.1 Inicio y fin de sesión Cuando arrancamos el sistema, deberemos identificarnos mediante un nombre de usuario (username o login) y una palabra clave (password). Si introducimos de manera incorrecta los datos anteriores, dependiendo del administrador, tendremos un número limitado de veces para repetir la contraseña, si superamos ese número nuestra cuenta se bloqueará y deberemos ir a hablar con el administrador del sistema para que la desbloquee. Podemos modificar nuestra contraseña mediante el comando passwd. Una vez dentro del sistema nos aparece el interprete de ordenes del sistema operativo (shell), como veremos más adelante, hay diversos tipos de shells que podremos personalizar. Tras terminar nuestro trabajo, deberemos salir del sistema de forma que todos nuestros procesos sean terminados de forma correcta, para ello utilizaremos las ordenes exit o logout o bien podremos pulsar la combinación de teclas Ctrl-D. Si lo que deseamos es apagar el computador, para hacerlo de un modo seguro sin que ningún proceso termine anormalmente, deberemos teclear la instrucción shutdown. 3.2 El shell de entrada Cuando entramos en el sistema, se nos asigna un shell por defecto que es establecido por el administrador del sistema. Sin embargo, nosotros podemos utilizar el shell que mejor nos parezca y cambiar ciertos archivos de configuración de modo que la próxima vez que entremos al sistema, se ejecute el shell que habíamos elegido. Para determinar el shell que estamos ejecutando hemos de consultar el valor de una variable dentro del shell, esta variable es $SHELL. Podemos visualizar el contenido de esta variable mediante la orden echo. $echo $SHELL /bin/csh Si deseamos cambiar el tipo de shell deberemos utilizar la orden chsh (change shell), su efecto no es inmediato, es decir, deberemos salir del sistema y volver a entrar para ver los cambios. Si deseamos cambiar el shell únicamente para una sesión y seguir utilizando el shell que tenemos por defecto, podemos invocar al shell directamente tecleando su nombre: sh,csh,tcsh,bash. Una vez hayamos terminado con este shell, deberemos cerrarlo mediante la orden exit como comentamos anteriormente. 4. INFORMACIÓN SOBRE COMANDOS: MAN / INFO Mediante la orden man, vamos a poder acceder al UNIX Programmer’s Manual que nos permitirá conocer que función cumple y que parámetros utiliza un comando cuando es ejecutado en el shell. La sintaxis de la orden man es: $man [opciones] [sección] orden Por ejemplo, si queremos saber que opciones tenemos para ejecutar la orden ls deberemos teclear: $man ls Dentro de las diversas opciones que podemos obtener, sólo veremos la opción “-k palabra_clave” que muestra la página del manual que contiene la palabra clave “palabra_clave” . Esta opción es muy útil cuando conocemos lo que queremos hacer, pero no sabemos el nombre de la orden. Equivalente a “man –k palabra_clave” es la orden “apropos palabra_clave”. Otra orden que nos va a proporcionar información más detallada sobre una instrucción es info. Gracias a esta podremos conocer los códigos que devuelve cada instrucción al SO cuando termina su ejecución. 5. OPERANDO CON EL SISTEMA DE FICHEROS En esta sección vamos a ver como podemos realizar operaciones básicas sobre el sistema de ficheros que hemos comentado anteriormente. COMANDOS cd argumento Change Cambia el directorio actual, la entrada “.” Hace Directory referencia al directorio actual y “..” al directorio padre mkdir argumento Make Crea un directorio con el nombre argumento Directory rmdir argumento Remove Borra un directorio denominado argumento. El Directory directorio debe estar vacío ls [argumentos] List Muestra el contenido de un directorio pwd Print working Muestra el directorio actual directory cat argumentos Orden multipropósito: muestra el contenido de un archivo o varios, concatena archivos, copia un archivo y crea un archivo de texto. mv fuente destino move file archivo rm archivo Mueve archivos Determina el contenido de un archivo Remove split –n argumento Borra archivos Parte argumento en trozos de n líneas 6. HISTORIA DE ORDENES La historia de ordenes consiste en ir almacenando las ordenes con sus respectivos parámetros que se le van dando a la shell para que ejecute. El sentido de mantener la historia es facilitar y hacer más rápida la repetición de alguna orden que ya habiamos ejecutado y poder reutilizar sus argumentos. La variable $history contiene el número de ordenes que se van a almacenar en la historia antes de descartar la orden más antigua almacenada. El valor para esta variable esta establecido por el administrador del sistema, si bien podemos cambiarlo asignándole otro valor a la variable. Para consultar el valor de las variables deberemos teclear set. Mediante la orden history, podemos ver todas las ordenes almacenadas hasta la última que se ejecutó. A la izquierda de cada orden podemos ver el número de orden que le corresponde, empezando por 1 para la orden más antigua. Reciclaje de ordenes anteriores A continuación vamos a describir el proceso para poder recuperar una orden anterior o parte de ella. Para esto utilizaremos el operador del signo de admiración “! “ . $!! #invoca la última orden $!numero #invoca la orden con número de suceso numero $!-desplazamiento_relativo #invoca la orden con número de suceso desplazamiento_relativo anterior a la última $!cadena_texto_comienzo_suceso $!?cadena_texto_contenida_en_suceso? P.ej. si estamos en suceso nº 7, tenemos varias formas de referenciar al suceso 5: 4$ ls 5$ mkdir dir1 6$ cd dir1 7$ !5 o 7$ !-2 o 7$!mk o 7$!?k 7. METACARACTERES Hay una serie de caracteres que tienen un significado superior al que tienen ellos mismos como caracteres, por eso se les denominan metacaracteres Todos los shells poseen un grupo de metacaracteres que dependiendo del contexto, tienen uno u otro significado. 7.1 Metacaracteres sintacticos Se utilizan como caracteres especiales de puntuación entre las ordenes. Son usados para combinar varias ordenes de UNIX con objeto de construir una única orden lógica. Suministran una forma de ejecución condicional basada en el resultado de la orden anterior. La siguiente tabla muestra los caracteres sintácticos y una descripción de su función: Metacaracteres Descripción ; Separador entre ordenes ejecutadas secuencialmente | Separador entre ordenes que están comunicadas mediante un cauce. La salida de la orden de la izquierda es la entrada de la orden situada a la derecha. () Se utilizan para aislar ordenes de forma que el resultado sea tratado como una única orden & Fuerza a ejecutar el trabajo en segundo plano || Separa ordenes de modo que la orden que sigue a este separador solo se ejecuta si la anterior ha fallado && Separa ordenes de modo que la orden que sigue a este separador solo se ejecuta si la anterior tiene éxito. Uniendo ordenes con ; Gracias a este separador, podremos escribir varias ordenes en una misma linea de comandos del shell y que se vayan ejecutando secuencialmente como si se hubieran introducido una a una en distintas lineas del shell. P.ej. 1$ cd /home/user1 ; ls Creando cauces con | El cauce conecta dos ordenes de modo que la salida de la orden situada a la izquierda del separador se vuelca en la entrada de la orden situada a la derecha del separador. P. ej. 2$ ls | sort Mediante esta orden, vamos a obtener el resultado del listado del directorio actual, ordenado alfabéticamente. Cuando a una orden no se le especifica salida ni entrada, coge por defecto la entrada y la salida estándar que se corresponden con el teclado y la pantalla respectivamente. Combinando ordenes con ( ) Cuando estamos ejecutando varias instrucciones secuencialmente, debemos separar y agrupar varias de estas ordenes para obtener el resultado que nosotros deseamos. Por ejemplo, las siguientes ordenes tienen resultados diferentes: $ date; ls | wc $ (date; ls) | wc La primera mostrará la fecha, luego el listado de ficheros y se contará el número de palabras resultantes sin tener en cuenta la fecha. En la segunda orden, si se contarán las palabras incluyendo la fecha, la cual, no será mostrada. Ejecutando ordenes en segundo plano Al ser un sistema multitarea, podemos tener varios procesos ejecutandose al mismo tiempo, uno en primer plano y los demás en segundo plano. Cuando ejecutamos un programa, por defecto pasará a ejecutarse en primer plano. Podemos especificar que el proceso se ejecute en segundo plano de forma que podamos seguir utilizando la linea de ordenes de la shell. Para hacer esto utilizaremos el carácter “&”: Orden argumentos & Cuando lanzamos un programa en segundo plano, antes de volver a aparecer el indicador de la línea de ordenes, se nos muestra un número entre corchetes seguido de otro numero. El primer número se corresponde con el número de trabajo y el segundo es el identificador de proceso que le asigna el SO. Si deseamos ejecutar una secuencia de ordenes en segundo plano, no debemos olvidarnos de englobarlas entre paréntesis ya que de lo contrario, corremos el riesgo de que la ejecución no sea secuencial y termine una orden antes que su predecesora: (orden1 ; orden 2) & Ejecución condicional de ordenes con || y && Cuando estamos haciendo una ejecución secuencial de ordenes, en algunos casos nos puede interesar que una orden se ejecute o no en función del éxito de la orden predecesora. Para ello contamos con los separadores || y &&. Si deseamos que una ejecución se ejecute tras finalizar con éxito su predecesora, deberemos separarlas con &&. Si por el contrario, queremos que una orden no se ejecute en caso de que su predecesora falle, las deberemos separar usando ||: Orden1 && Orden2 ? Orden2 se ejecutará si Orden1 finaliza CON éxito Orden1 || Orden2 ? Orden2 se ejecutará si Orden1 finaliza SIN éxito La definición de éxito de una orden depende de la implementación de esta, para conocerla deberemos utilizar la página del manual o información más detallada (info orden). 7.2 Metacaracteres de nombre de archivos Gracias a estos metacaracteres podremos crear patrones de igualación para la sustitución de nombres de ficheros: ? Es igual a cualquier carácter simple * Es igual a cualquier secuencia de cero o más caracteres [] Designa un rango de caracteres a el cual puede ser igualado un carácter simple. {} Define una serie de caracteres a ser igualados. ~ Se utiliza para abreviar el nombre del directorio home del usuario Ejemplos: Carácter ?: Tenemos un directorio con los ficheros: Num1dat.txt Num2dat.txt Num3dat.txt Num4dat.txt Para listar estos ficheros podríamos utilizar: $ ls Num?dat.txt Carácter * Para listar los ficheros anteriores bastaría con escribir: $ls * $ls N* $ls Num* etc. Carácter [ ] Dado el conjunto de ficheros anterior, queremos listar solo los ficheros comprendidos entre el rango 2 – 4, entonces deberemos escribir: $ls Num[2-4]dat.txt o también $ls Num[2-4]* $ls *[2-4]* Carácter { } Ahora queremos listar los ficheros Num1dat.txt Num2dat.txt y Num4dat.txt, en esta ocasión no podemos utilizar el intervalo que vimos antes, lo vamos a sustituir por { }: $ls Num{1,2,4}dat.txt o bien $ls Num{1,2,4}* $ls *{1,2,4}* Uso de ~ Como mencionamos anteriormente, cada usuario tiene asignado un directorio home donde aparece cuando inicia la sesión. Cuando queramos hacer referencia a este directorio, no hace falta que especifiquemos el camino completo, basta con sustituirlo por “~”, por ejemplo, si nos encontramos fuera de nuestro directorio y queremos volver tan solo deberemos teclear: $cd ~ Y apareceremos en nuestro directorio home. 7.3 Metacaracteres de citación Gracias a estos caracteres podremos poder utilizar los caracteres que hemos visto hasta ahora con su significado normal de modo que no sean interpretados como metacaracteres. \ Evita que el siguiente carácter sea interpretado como un metacaracter " Evita que la cadena encerrada entre comillas sea interpretada como metacaracteres ' Evita que la cadena encerrada entre comillas sea interpretada metacaracteres u ordenes como 7.4 Metacaracteres de entrada/salida En UNIX, al iniciar un programa, se abren tres ficheros: la entrada estándar (stdin), al salida estándar (stdout) y la salida del error (stderr). Como comentamos antes, la entrada estándar es el teclado y las salidas son la pantalla. Con el uso de los siguientes metacaracteres podremos modificar el flujo de información entre estos tres elementos. < fichero Redirección de la entrada estándar a fichero > fichero Redirección de la salida estándar a fichero >& fichero Redirecciona la salida estándar y la de error y se escriben en fichero >&! fichero Redirecciona la salida estándar y la de error y se escriben en fichero.Si fichero existe, se sobrescribe. >> fichero Redirecciona la salida, añadiendose al final del contenido de fichero >>& fichero Redirecciona la salida estándar y la de error y se añaden a fichero. << palabra El shell toma con entrada estándar de la orden todas las lineas que se introduzcan hasta que aparezca palabra. | Crea un cauce pipe. |& Crea un cauce redirigiendo la salida estándar y la salida de error.