PRÁCTICAS DE SISTEMAS OPERATIVOS I

SEGUNDA SESIÓN


  1. Variables de entorno

    La conexión con el servidor que estamos usando es programable. Gran parte de estas prácticas la vamos a dedicar a estudiar cómo programar en este entorno. Una de las características primordiales de todo lenguaje de programación son las variables. Y la programación que vamos a ver no está, como es natural, exenta de ellas. A estas variables se les denomina variables de entorno.

    Los nombres de variables pueden contener letras del alfabeto inglés, tanto mayúsculas como minúsculas, números, y el carácter de subrayado (_). Pero no pueden comenzar por un número y es tradición usar letras mayúsculas para diferenciarlas bien de las órdenes. Son nombres de variables válidos, pues, Pepa, Avelino, BURLA2, _MmMmM_, etc. Y no lo serán, 6TOROS6, HOL@ y así.

    Lo primero que podermos hacer con una variable es establecer su valor. Todas las variables son cadenas de caracteres, por lo que, aunque escribamos números, internamente se almacenan caracteres. Asignemos un valor a una variable:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ CENTRO='Facultad de Ciencias'
    
    El apóstrofo, que es el carácter que se encuentra en el teclado español debajo del signo de cierre de interrogación, no es obligatorio, pero observad qué es lo que ocurre si no lo ponemos:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ UNIVERSIDAD=Universidad de Salamanca
    bash: de: command not found
    
    Al encontrarse un espacio en blanco, el ordenador se cree que ahí acaba la cadena. Asigna Universidad a la variable UNIVERSIDAD y trata de ejecutar la palabra de como si de una orden se tratase. Como no lo es, nos da el mensaje en inglés de orden no encontrada.

    Para acceder al contenido de una variable, se antepone a su nombre el símbolo del dólar ($):
    <gyermo@ENCINA>/usuarios/profes/gyermo$ $CENTRO
    bash: Facultad: command not found
    
    De nuevo, obtenemos un error pero es evidente el porqué. Antes de ejecutar cualquier orden el ordenador sustituye las apariciones de las variables por su correspondiente valor. A continuación, se dispone a ejecutar el resultado y se piensa que la primera palabra (Facultad) es una orden que le estamos dando y no la entiende. Si lo que queremos es que nos muestre el contenido de una variable, necesitamos una orden nueva para ello. La orden es echo:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $CENTRO
    Facultad de Ciencias
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo Mi centro es la $CENTRO
    Mi centro es la Facultad de Ciencias
    
    Ejercitémonos con las variables. Vamos a mostrar el resultado del último partido de fútbol del Trofeo Rector, con ayuda de la variable CENTRO y otra nueva, CENTRO2, de modo que aparezca exactamente esto por la pantalla: Facultad de Ciencias2‑Derecho0(*):
    <gyermo@ENCINA>/usuarios/profes/gyermo$ CENTRO2=Derecho
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $CENTRO2-$CENTRO20
    Derecho-
    
    ¿Qué es lo que ha ocurrido? ¿Por qué no nos obedece el ordenador? La respuesta es simple. Porque no adivina nuestros pensamientos. Al poner $CENTRO2 él se piensa que pedimos que imprima la variable CENTRO2 e imprime esa variable, que vale Derecho. En estos casos ambiguos, tenemos que ayudarle para que sepa hasta dónde llega el nombre de la variable. Lo hacemos con ayuda de las llaves:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo ${CENTRO}2-${CENTRO2}0
    Facultad de Ciencias2-Derecho0
    
    Otra sutileza que debéis saber: al ser el espacio en blanco un separador, para el ordenador lo mismo le da 1 que 80. Tratemos de que salga por la pantalla: Facultad␣de␣Ciencias,␣␣␣Universidad␣de␣Salamanca. En la cadena se han marcado con los espacios para que veáis que hay tres entre la coma y Universidad:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $CENTRO,   $UNIVERSIDAD
    Facultad de Ciencias, Universidad de Salamanca
    
    Aunque hemos puesto tres espacios, como el espacio actúa de separador, el ordenador lo trata como si fuera uno. ¿Y si ponemos la frase entre apóstrofos? Recordad que podéis usar las flechas para editar la orden anterior y ahorrar tiempo...
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo '$CENTRO,   $UNIVERSIDAD'
    $CENTRO,   $UNIVERSIDAD
    
    ¡Uy! Parece que hemos logrado que salgan los tres espacios en blanco después de la coma, pero el ordenador toma todo al pie de la letra. Incluso el signo $ lo interpreta tal cual y no como indicador de que lo que viene a continuación es una variable. Si solamente tuviéramos la posibilidad de que hubiera algo que le dijera al ordenador que interpretarse todo literalmente salvo el carácter $... Pues lo hay:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo "$CENTRO,   $UNIVERSIDAD"
    Facultad de Ciencias,   Universidad de Salamanca
    
    Nos basta con ponerlo entre comillas dobles. Las comillas dobles, aparte del significado de $, también respetan los significados de !, \ y `. Alguno de ellos los veremos después. El último es el acento francés parecido al nuestro, pero mirando a Cuenca. En el teclado español se obtiene pulsando la tecla de dicho acento y la barra espaciadora a continuación. ¿Con el siguiente ejemplo adivináis para qué sirve?
    <gyermo@ENCINA>/usuarios/profes/gyermo$ LISTADO=`ls`
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $LISTADO
    backup bin CARTAS chgrp.2 gyermo-encina-2005-03.tar.gz mail MANTEJO PRIVADO PRUEBA 
    public_html SESION3 SESION6 TEMP
    
    Por si andáis un poco despistadillos, esta es la respuesta: lo que pongáis dentro de un par de esos acentos, primero lo ejecuta el ordenador y el resultado, en lugar de sacarlo por la pantalla, lo pone en lugar del par de acentos y su contenido, como si estuviera entre apóstrofos. Dicho de otro modo, primero ejecuta el ls que le hemos puesto en el ejemplo y, después, es como si alguien hubiera tecleado la siguiente línea:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ LISTADO='backup bin CARTAS chgrp.2 gyermo-encina-2005-03.tar.gz
    mail MANTEJO PRIVADO PRUEBA public_html SESION3 SESION6 TEMP'
    
    ¿Sabríais responder qué es lo que pasará si tecleáis echo `ls`? Hacedlo. ¿Lo habéis adivinado?

    Para acabar con esta sección, debemos mencionar la manera de desdefinir una variable de entorno. Podríais pensar que asignando un valor vacío la variable deja de estar definida, pero no es así. En ese caso, la variable sí que sigue definida. Si queremos que ocurra como si nunca la hubiéramos definido, debemos usar la orden unset:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ UNIVERSIDAD="Universidad de Salamanca"
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo Mi universidad es la $UNIVERSIDAD
    Mi universidad es la Universidad de Salamanca
    <gyermo@ENCINA>/usuarios/profes/gyermo$ unset UNIVERSIDAD
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo Mi universidad es la $UNIVERSIDAD
    Mi universidad es la
    
    ____________________________
    (*) Los personajes y hechos relatados en estas prácticas son ficticios. Cualquier semejanza con la realidad, es pura coincidencia.

    El significado del carácter \ es muy parecido al que tiene en C. Seguido de ciertas letras permite referirse a caracteres de control. Como al tener ese uso, el propio carácter queda invalidado para representarse a sí mismo, si lo que queremos es que aparezca uno de estos caracteres en la cadena, debemos doblarlo (\\). El carácter \ en el contexto que nos ocupa también sirve para privar de su significado especial a otros caracteres como $ o el espacio en blanco, sin necesidad de que los metamos entre apóstrofos. Así, por ejemplo, para que podamos imprimir esta cadena o asignarla a una variable sin usar apóstrofos: La␣cuenta␣asciende␣a:␣␣␣\$137,03\, debemos escribir:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo La\ cuenta\ asciende\ a:\ \ \ \\\$137,03\\
    La cuenta asciende a:   \$137,03\
    
    Si lo asignamos a una variable, debemos tener cuidado, pues aunque dentro de la variable estén los tres espacios, el ordenador los vuelve a colapsar en uno si no tenemos cuidado:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ CUENTA=La\ cuenta\ asciende\ a:\ \ \ \\\$137,03\\
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $CUENTA
    La cuenta asciende a: \$137,03\
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo "$CUENTA"
    La cuenta asciende a:   \$137,03\
    
    El significado especial del carácter ! no lo veremos en estas prácticas. El que esté interesado puede consultar la página de manual de la orden bash.

    Por otro lado, el manejo de arrays es muy sencillo. Basta con que hagamos referencia en una asignación a un elemento de un array para que se pueda usar. No es necesario, pues, declarar el array con antelación. Por ejemplo:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ n[4]=no n[6]=no n[8]=no n[9]=no n[10]=no n[12]=no n[14]=no
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo 7 ${n[7]} es un número primo
    7 es un número primo
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo 12 ${n[12]} es un número primo
    12 no es un número primo
    
    Para referirse a un elemento del array, como veis, es necesario usar las llaves.

    Se puede obtener todos los valores de un array, así como los índices correspondientes, como se ve en el siguiente ejemplo:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ m[0]=3 m[1]=1 m[3]=1
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo ${m[*]}
    3 1 1
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo ${!m[*]}
    0 1 3
    
    Notad que el elemento de índice 2 está ausente. En las versiones modernas de la shell, también se dispone de arrays asociativos (esto es, aquellos cuyos índices pueden ser cadenas de caracteres). En este ejemplo, usamos uno para guardar la edad de una serie de personas:
    gyermo@mirto:~$ declare -A EDAD
    gyermo@mirto:~$ EDAD[Lucas]=40 EDAD[Silvia]=37 EDAD[JonAs]=3 EDAD[Daniel]=1
    gyermo@mirto:~$ echo La edad de JonAs es ${EDAD[JonAs]}.
    La edad de JonAs es 3.
    
    También funciona, en este caso, tanto el listado de valores como el de índices, aunque no se respeta el orden de asignación:
    gyermo@mirto:~$ echo ${EDAD[*]}
    3 40 1 37
    gyermo@mirto:~$ echo ${!EDAD[*]}
    JonAs Lucas Daniel Silvia
    
    Al igual que ocurre con las variables, se puede borrar un array completo o alguno de sus elementos mediante la orden unset.

    Finalmente, otra orden de la shell interesante es la orden eval. Toma una expresión cualquiera, la expande y el resultado de la expansión lo ejecuta. Esto incluye, cómo no, expresiones contenidas en variables. Por ejemplo:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ORDEN="ls -l"
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ eval $ORDEN
    total 4
    lrwxrwxrwx   1 gyermo   profes        14 ago 19 19:40 ReyesMagos.txt -> SantaClaus.txt
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    
  2. Variables de entorno del sistema

    Existen ciertas variables que tienen un significado especial para el sistema. En realidad, ya nos hemos encontrado con algunas de ellas. Mismamente, en la sesión anterior, al configurar nuestra cuenta, lo que hicimos fue asignar valores a alguna de ellas: PS1, por ejemplo.

    La cantidad de variables del sistema es grande y no siempre se encuentran en todas las versiones del sistema, por lo que solamente destacaremos algunas de ellas:
    De todas ellas, quizá la más importante sea la variable PATH. La mayor parte de órdenes de UNIX no son sino programas que han hecho otras personas, los han compilado y se encuentran en algún directorio del disco duro. Cuando tecleamos una orden, como ls, el ordenador busca un programa que se llame así y lo ejecuta. ¿Dónde lo busca? Pues en los directorios que se especifiquen en la variable de entorno PATH. Si queremos saber dónde encuentra a un determinado programa, podemos usar la orden which:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $PATH
    /opt/SUNWspro/bin:[...]:/usr/bin:/usr/local/bin:[...]:/home/gyermo/bin:/usr/bin:/usr/ucb:/usr/ccs/bin:/etc:.
    <gyermo@ENCINA>/usuarios/profes/gyermo$ which ls
    /usr/bin/ls
    <gyermo@ENCINA>/usuarios/profes/gyermo$ ls -l /usr/bin/ls
    -r-xr-xr-x   1 root     bin        27400 ene 24  2007 /usr/bin/ls
    
    Los ficheros que representan órdenes suelen pertenecer a root y tener permisos de ejecución para todos los usuarios, como se ve en el ejemplo.

    Si queremos saber el nombre de todas las variables, tanto del sistema como definidas por nosotros, daremos la orden set:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ set
    BASH=/usr/bin/bash
    BASH_ARGC=()
    BASH_ARGV=()
    BASH_LINENO=()
    BASH_SOURCE=()
    BASH_VERSINFO=([0]="3" [1]="00" [2]="16" [3]="1" [4]="release" [5]="sparc-sun-solaris2.10")
    BASH_VERSION="3.00.16(1)-release"
    CENTRO="Facultad de Ciencias"
    CENTRO2=Derecho
    COLUMNS=113
    CUENTA="La cuenta asciende a:   \$137,03\"
    [...]
    
  3. Operaciones aritméticas

    Antiguamente, se denominaba a los ordenadores cerebros electrónicos. Sin embargo, a veces no saben ni cuánto es 1 más 1:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo 1+1
    1+1
    
    Bueno, en realidad estamos siendo algo injustos. Ya sabemos que esos unos son, en realidad, caracteres. Para que el ordenador realice la operación es necesario que le avisemos de que eso que le pasamos son números. Esto se logra así:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $((1+1))
    2
    
    Podemos usar también variables:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ TRES=3
    <gyermo@ENCINA>/usuarios/profes/gyermo$ echo $(($TRES*$TRES))
    9
    
    Las operaciones son iguales a las de C, salvo la exponenciación, que aquí se expresa con dos asteriscos seguidos (**). También los operandos y el resultado están limitados a los números enteros.
  4. Expansión de argumentos. Expresiones regulares

    Muchas de las órdenes que hemos visto admiten un número variable de argumentos. Los argumentos variables suelen ser rutas de fichero y suelen ir al final de la orden. Por ejemplo, si queremos cambiar los permisos de más de un fichero a la vez, ponemos las rutas de los ficheros que queremos cambiar al final. Por ejemplo:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ cd CARTAS/
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    lrwxrwxrwx   1 gyermo   profes        14 ago 19 19:40 ReyesMagos.txt -> SantaClaus.txt
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ rm ReyesMagos.txt 
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ cp SantaClaus.txt ReyesMagos.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    -rw-r--r--   1 gyermo   profes       186 ago 21 13:31 ReyesMagos.txt
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ chmod 600 ReyesMagos.txt SantaClaus.txt 
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    -rw-------   1 gyermo   profes       186 ago 21 13:31 ReyesMagos.txt
    -rw-------   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    
    En el ejemplo, primero hemos vuelto a hacer que ReyesMagos.txt sea un fichero normal y, luego, con una única orden chmod hemos cambiado los permisos de los dos ficheros de modo que los mantengamos alejados de miradas indiscretas.

    Esto que hemos hecho a mano se puede automatizar con ayuda de lo que se conoce como expresiones regulares. Una expresión regular es una cadena de caracteres que contiene unos símbolos de significado especial. Tiene la propiedad de que, cuando se les ofrece otra cadena cualquiera, o bien casa con la expresión regular, o no. Por supuesto que existen reglas para determinar si la expresión regular casa con una cadena, aunque existen diferentes tipos de expresiones regulares. En concreto, las reglas que siguen las expresiones regulares que se usan en la línea de órdenes son las siguientes:
    1. *: este carácter casa con cualquier número de caracteres de la cadena, incluso cero
    2. ?: este carácter casa con justo un carácter de la cadena, aunque puede ser cualquiera
    3. [abc]: esta expresión casa con cualquiera de los caracteres que pongamos dentro de los corchetes, en el ejemplo a, b o c. También se admiten rangos de caracteres, separados por un guion. Por ejemplo, [a-z] casa con cualquier letra minúscula del alfabeto inglés.
    4. [!abc] o [^abc]: igual que el caso anterior, pero al contrario. En el ejemplo, casa con cualquier carácter que no sea ni a, ni b, ni c.
    5. Cualquier otro carácter: solamente casa con él mismo


    Cuando el ordenador detecta una expresión regular en una orden, trata de ver si existe alguna ruta que case con la expresión de todas las posibles. Si encuentra rutas que casen, sustituye la expresión regular por dichas rutas. Si no, la deja tal cual. Veamos ejemplos de uso de expresiones regulares con la orden ls:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    -rw-------   1 gyermo   profes       186 ago 21 13:31 ReyesMagos.txt
    -rw-------   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls [!R]*
    SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls *.txt
    ReyesMagos.txt  SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls *a?s*
    SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls *e?M*
    ReyesMagos.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls *a*s?t*
    ReyesMagos.txt  SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls *s??a*
    *s??a*: No such file or directory
    
    Las expresiones regulares pueden ser traducidas más o menos al lenguaje común, así la primera del ejemplo sería algo como lista todos los ficheros que no empiecen por R mayúscula. La segunda diría: lista todos los ficheros que acaben en .txt. Y así, sucesivamente.

    Es importante que reparéis en que la orden ls u otra cualquiera, si la expresión regular casa, no llega nunca a verla. El ordenador ya le ofrece el resultado de haberla aplicado. Para que os convenzáis de ello, basta con impedir al ordenador la expansión, metiendo la expresión entre comillas:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    -rw-------   1 gyermo   profes       186 ago 21 13:31 ReyesMagos.txt
    -rw-------   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls "*.txt"
    *.txt: No such file or directory
    
    Al ponerlo entre comillas, el asterisco pierde su valor especial. El ordenador no expande la expresión regular y se la pasa tal cual a la orden ls. Como la orden no ve ningún fichero que se llame *.txt, pues da un error.

    Otra opción más que nos ofrece la shell es la expansión de llaves. Toma dos formas, una numérica y otra alfabética. En la numérica, nosotros indicamos un rango y la shell completa argumentos para cada uno de los valores de este rango. Por ejemplo, veamos una manera fácil de referirnos a los 10 temas que hemos hecho en TeX para la teoría de una asignatura:
    <gyermo@ENCINA>/usuarios/profes/gyermo/DOCENCIA$ echo tema{1..10}.tex
    tema1.tex tema2.tex tema3.tex tema4.tex tema5.tex tema6.tex tema7.tex tema8.tex tema9.tex tema10.tex
    
    La segunda forma, cuando se trata de caracteres, estos van separados por comas y la shell construye una palabra por cada una de las posibilidades, como se puede comprobar en este ejemplo:
    <gyermo@ENCINA>/usuarios/profes/gyermo/DOCENCIA$ echo para{lela,bólica,dójica,métrica}mente
    paralelamente parabólicamente paradójicamente paramétricamente
    
    Es útil para, por ejemplo, borrar todos los ficheros de imágenes del directorio actual que empiecen por auto (rm auto*.{jpg,jpeg,gif,png}).
  5. Valor devuelto

    Las órdenes de UNIX devuelven un valor entero y mayor o igual que cero cuando acaban su ejecución. Tradicionalmente, un valor igual a cero indica que la orden se ha ejecutado sin problemas y un valor mayor que cero, que la orden ha tenido un error.

    Para saber qué significa cada uno de los valores que devuelve una orden, hay que consultar la página de manual.

    Podemos saber cuál es el valor que ha devuelto una orden mediante la variable especial ?. Pero debemos hacerlo justo después de haber ejecutado la orden, pues si no, el valor que tenga la variable ya habrá sido reescrito por la ejecución de cualquier otra orden.

    Veamos un ejemplo:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    -rw-------   1 gyermo   profes       186 ago 21 13:31 ReyesMagos.txt
    -rw-------   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ echo $?
    0
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l PopeyeElMarino.txt
    PopeyeElMarino.txt: No such file or directory
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ echo $?
    2
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ echo $?
    0
    
    La primera vez que imprimimos el valor devuelto nos da un 0, pues la ejecución anterior fue exitosa. La segunda vez, nos da un 2, pues el ls falló. Finalmente, la tercera vez, nos devuelve 0, pues se refiere a la ejecución anterior y la ejecución anterior fue el segundo echo $? que, evidentemente, no falló.
  6. Interfaz con C

    Como ya conocéis de las asignaturas de programación, un programa escrito en C puede recibir argumentos y puede devolver valores, justo como cualquier orden de las que hemos visto. De hecho, la gran mayoría de esas órdenes, no son sino programas escritos en C.

    Recordemos cómo se toman los argumentos y cómo se devuelve un valor al sistema operativo, con este sencillo programa:
    #include <stdio.h>
    
    int main(int argc,char *argv[])
     {int i;
    
      if (argc==1)
       {fprintf(stderr,"Al programa %s no se le han pasado argumentos.\n",
                argv[0]);
        return 1;}
    
      for (i=1;i<argc;++i)
        fprintf(stderr,"El argumento %d es: \"%s\"\n", i, argv[i]);
    
      return 0;
      }
    
    Hacemos un directorio en nuestro directorio de conexión que se llame ARGUMENTOS. Dentro de él, editamos un fichero que se llame argumentos.c. Lo compilamos y ejecutamos varias pruebas, con el resultado esperado:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ gcc argumentos.c -o argumentos
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ argumentos
    Al programa argumentos no se le han pasado argumentos.
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ echo $?
    1
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ argumentos Pepa
    El argumento 1 es: "Pepa"
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ echo $?
    0
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ argumentos ../CARTAS/*
    El argumento 1 es: "../CARTAS/ReyesMagos.txt"
    El argumento 2 es: "../CARTAS/SantaClaus.txt"
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ echo $?
    0
    
    En el último caso, al ser el argumento una expresión regular, el ordenador lo ha sustituido antes de pasárselo a nuestro programa, como hemos visto.


    Lo que ya no es tan conocido es que a un programa en C, el ordenador también le pasa variables de entorno. Modifiquemos el listado anterior para curiosear en ellas:
    #include <stdio.h>
    
    int main(int argc,char *argv[],char *environ[])
     {int i; char **cpp;
    
      for (cpp=environ; *cpp!=NULL; ++cpp)
        fprintf(stderr,"Variable de entorno: %s\n", *cpp);
    
      if (argc==1)
       {fprintf(stderr,"Al programa %s no se le han pasado argumentos.\n",
                argv[0]);
        return 1;}
    
      for (i=1;i<argc;++i)
        fprintf(stderr,"El argumento %d es: \"%s\"\n", i, argv[i]);
    
      return 0;
      }
    
    No os olvidéis de volver a compilar antes de ejecutar el programa:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ gcc argumentos.c -o argumentos
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ argumentos
    Variable de entorno: MANPATH=:/usr/sfw/man:/usr/local/man:/opt/SUNWspro/man:/opt/SUNWste/license_tools/man:/usr/share/man:/opt/sfw/man
    Variable de entorno: LC_MONETARY=es_ES.ISO8859-1
    Variable de entorno: TERM=xterm
    [...]
    Variable de entorno: LC_CTYPE=es_ES.ISO8859-1
    Variable de entorno: ORACLE_HOME=/opt/oracle/product/10.2.0/Db_1
    Variable de entorno: ENCINA=192.168.201.3
    Variable de entorno: _=./argumentos
    Al programa argumentos no se le han pasado argumentos.
    
    Si repasáis la lista de variables de entorno que recibe el programa, veréis que no están las que definísteis más arriba. La razón es que el ordenador solamente pasa a los programas aquellas variables que habéis declarado como exportables (por así decirlo, que no son privadas vuestras). Si queréis hacer pública una variable de entorno lo tenéis que decir:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ export FACULTAD
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ argumentos 
    Variable de entorno: MAJUELO=129.168.201.5
    Variable de entorno: MANPATH=:/usr/sfw/man:/usr/local/man:/opt/SUNWspro/man:/opt/SUNWste/license_tools/man:/usr/share/man:/opt/sfw/man
    Variable de entorno: LC_MONETARY=es_ES.ISO8859-1
    Variable de entorno: TERM=xterm
    [...]
    Variable de entorno: LC_CTYPE=es_ES.ISO8859-1
    Variable de entorno: FACULTAD=Facultad de Ciencias
    Variable de entorno: ORACLE_HOME=/opt/oracle/product/10.2.0/Db_1
    Variable de entorno: ENCINA=192.168.201.3
    Variable de entorno: _=./argumentos
    Al programa argumentos no se le han pasado argumentos.
    
    A veces, resulta conveniente definir una variable solo para la ejecución de un programa concreto, sin que afecte a las definiciones de las variables de nuestra shell. En ese caso, puede usar la siguiente sintaxis:
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ FACULTAD="Mi Facultad" argumentos 
    Variable de entorno: MAJUELO=129.168.201.5
    Variable de entorno: MANPATH=:/usr/sfw/man:/usr/local/man:/opt/SUNWspro/man:/opt/SUNWste/license_tools/man:/usr/share/man:/opt/sfw/man
    Variable de entorno: LC_MONETARY=es_ES.ISO8859-1
    Variable de entorno: TERM=xterm
    [...]
    Variable de entorno: LC_CTYPE=es_ES.ISO8859-1
    Variable de entorno: FACULTAD=Mi Facultad
    Variable de entorno: ORACLE_HOME=/opt/oracle/product/10.2.0/Db_1
    Variable de entorno: ENCINA=192.168.201.3
    Variable de entorno: _=./argumentos
    Al programa argumentos no se le han pasado argumentos.
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ echo $FACULTAD
    Facultad de Ciencias
    

    Como se puede observar, una vez ejecutado el programa, la shell conserva el valor anterior que tuviera la variable.

    Otra manera también estándar de obtener el valor de una variable de entorno es mediante la función de la biblioteca de C:
           #include <stdlib.h>
           char *getenv(const char *name);
    
    A la función se le pasa el nombre de la variable y devuelve su valor, o NULL en el caso de que la variable no esté definida.
  7. Ejercicio

    Hacer un programa en C con una capacidad básica de internacionalización. En concreto:
    1. No se le pase ningún argumento por la línea de órdenes
    2. Si se le pasa alguno, se imprima un mensaje de error y se ponga la forma de uso
    3. El programa analiza la variable de entorno LANG:
      • si empieza por "es", imprime el mensaje: Hola, ¿qué tal?
      • si empieza por "sal", pone: ¿Qué pasa, majo?
      • en cualquier otro caso, la frase es: What's up, man?
  8. Tareas domésticas. Copiar, renombrar, mover, borrar...

    No pasará un día de conexión con el servidor en que no tengáis que hacer alguna labor de mantenimiento. Suponed que nos damos cuenta de que nuestra carta a los Reyes Magos de sesiones anteriores nos vale, con muy poco esfuerzo, como carta a Papá Noel. Si no la tenĂ©is a mano, podéis crear una, aunque sea vacía con la orden touch ReyesMagos.txt. Nos servirá igual. Pues nada, a copiarla:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls
    ReyesMagos.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ cp ReyesMagos.txt PapANoel.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:57 PapANoel.txt
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:32 ReyesMagos.txt
    
    Aunque, también, eso de Papá Noel suena un poco cursi. Mejor Santa Claus, que los tiempo de gloria franceses hace tiempo que pasaron. Lo renombramos:
    <gyermo@ENCINA</usuarios/profes/gyermo/CARTAS$ mv PapANoel.txt SantaClaus.txt
    <gyermo@ENCINA</usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:32 ReyesMagos.txt
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    
    Como veis, desde el punto de vista de Unix, renombrar y mover son una misma cosa. Resumiento, las órdenes de mantenimiento de ficheros son:
    1. cp (copy): copia el primer fichero en el segundo
    2. mv (move): mueve o renombra el primer fichero
    3. rm (remove): borra un fichero


    Para ver cuánto espacio está ocupando un directorio y todos los subdirectorios que contiene, usamos du -h:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:32 ReyesMagos.txt
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ du -h .
       3K   .
    
    3K son 3*1024 = 3072 bytes. Si cada fichero ocupa 186 bytes, esto es, los dos ficheros juntos ocupan 186+186 = 372 bytes, ¿dónde se han quedado los 3072-372 = 2700 bytes restantes? ¿Quién me está robando los bytes?

    La respuesta a este enigma está en que, como veremos en teoría, el disco duro está organizado en bloques de tamaño fijo. Se ve que, en el servidor, estos bloques son de 1K, por lo que, aunque nuestros ficheros son más pequeños, lo mínimo que ocupa cada uno es un bloque, o sea, 1K. ¿Y la K que queda, pues son 3? Pues la usa el directorio que, en el fondo también es un fichero, para saber qué es lo que tiene dentro. El desperdicio de espacio de disco debido a que los bloques no se ocupan al completo de su capacidad, se conoce técnicamente como fragmentación interna.

    La shell nos permite renombrar órdenes, o incluso órdenes con argumentos, y formar un alias. Por ejemplo, si definimos el alias listar como sustituto de ls -l podemos referirnos a esa orden mediante su alias:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ alias listar="ls -l"
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ listar
    total 2
    -rw-r--r--   1 gyermo   profes       186 ago 19 13:22 ReyesMagos.txt
    
  9. Acertijo

    Podemos crear un fichero que se llame --help muy fácilmente:
    <gyermo@ENCINA</usuarios/profes/gyermo/CARTAS$ cat > --help
    Hola
    [[Pulsad CTRL+D]]
    <gyermo@ENCINA</usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    [[...]]
    -rw-r--r--   1 gyermo   profes         5 sep 10 21:53 --help
    [[...]]
    
    Pero, ¿cómo lo borramos? ¿Y en Linux? Por borrar se entiende borrarlo completamente de modo que no aparezca en el listado del directorio. No basta con vaciar su contenido.
  10. Tareas domésticas avanzadas. Enlaces duros y blandos

    Acabamos el apartado anterior con nuestro disgusto al comprobar que la mayor parte del disco duro, por el que hemos pagado nuestro buen dinerito, está desaprovechado. Al menos, en lo que a los ficheros pequeños se refiere. Veamos en esta sección si podemos hacer algo.

    Un sistema de ficheros UNIX está organizado de modo que los datos de cada fichero están en un lugar diferente del disco duro de donde se almacena su nombre. El nombre del fichero se almacena dentro del propio directorio que, a todos los efectos, no es más que un fichero especial. Los datos del fichero se acceden a través de los inodos. Existe una tabla de inodos en el disco y cada inodo tiene un número que lo identifica que no es más que el índice de la tabla donde se encuentra el propio inodo. Veamos los números de inodo de nuestras dos cartas. Lo hacemos con la opción -i de ls:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -i
         66225 ReyesMagos.txt       66223 SantaClaus.txt
    
    Es evidente que estos números serán diferentes cuando probéis vosotros el ejemplo, pues los datos de esos ficheros estarán en posiciones diferentes en la tabla de inodos de vuestro disco. En mi caso, el inodo 66225 se encuentran los datos de la carta a los Reyes Magos. Por su parte, en el inodo 66223 se encuentran los datos de la carta a Santa. Como una es copia exacta de la otra, la carta exactita está almacenada dos veces en el disco duro. ¿No podríamos hacer que los datos, al ser iguales, estuvieran una sola vez en el disco? Pues claro que sí. Lo que necesitamos es crear lo que se denomina un enlace duro. Para ello, borramos uno de los ficheros y lo enlazamos al otro:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ rm ReyesMagos.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 2
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ln SantaClaus.txt ReyesMagos.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    -rw-r--r--   2 gyermo   profes       186 ago 19 18:57 ReyesMagos.txt
    -rw-r--r--   2 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    
    Fijaos en que la orden ln primero lleva con qué queremos enlazar y, luego, qué es lo que queremos enlazar. Parecería más lógico que fuera al revés, pero es así. Después de hechos los pasos anteriores, la situación se parece mucho a la de antes. Tenemos dos "ficheros", pero sabemos que los datos están una sola vez. Veamos ahora los inodos y lo que ocupa nuestro directorio:
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -i
         66223 ReyesMagos.txt       66223 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ du -h
       2K   .
    
    Hemos conseguido nuestro objetivo. Ahora el directorio, como los datos están compartidos, ocupa solamente 2K (1K para los datos, 1K para el directorio) en lugar de 3K. Si sois muy observadores, os daréis cuenta de que la salida del ls -l cuando teníamos dos ficheros auténticos y ahora que tenemos dos enlaces, es ligeramente distinta. El número misterioso que nos da ls a continuación de los permisos ha cambiado. La razón es que ese número significa cuántos ficheros están compartiendo los datos de ese. Antes los datos eran propios de cada fichero, por lo que aparecía un 1, y ahora están compartidos por dos ficheros, por lo que aparece un 2.

    Existe un segundo tipo de enlace, que se denomina enlace blando. Funcionalmente es muy parecido al duro, pero internamente funciona de manera diferente. Una vez establecido un enlace duro, ninguna de las partes es más importante que las otras. Todas ellas, comparten en igualdad los mismos datos.

    En un enlace blando, una de las partes es la importante, la que posee los datos y la otra, solamente apunta a la primera. Cuando pedimos al sistema operativo que nos dé los datos de la segunda parte (la subordinada), el sistema operativo ve que está apuntado a la otra (la principal) y nos da los datos de esta. Observad el proceso anterior, pero con enlaces blandos (también conocidos como enlaces simbólicos):
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ rm ReyesMagos.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 2
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ln -s SantaClaus.txt ReyesMagos.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -l
    total 4
    lrwxrwxrwx   1 gyermo   profes        14 ago 19 19:40 ReyesMagos.txt -> SantaClaus.txt
    -rw-r--r--   1 gyermo   profes       186 ago 19 18:57 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls -i
         66225 ReyesMagos.txt       66223 SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ du -h
       3K   .
    
    Observad las siguientes diferencias:
    1. Se añade la opción -s a ln para pedir que el enlace sea simbólico
    2. ls -l marca el enlace simbólico no como un fichero (-), sino como enlace (l)
    3. ls -l muestra a dónde está apuntando el enlace al final de la línea
    4. El tamaño del fichero no es el de los datos apuntados, sino que al ser el propio enlace un fichero especial que apunta a otro, sus propios datos son la ruta de acceso a lo que está apuntando (en este caso mide 14 bytes, lo que mide la cadena de caracteres SantaClaus.txt)
    5. Vistos como ficheros, enlace y enlazado tienen datos diferentes, luego tienen que tener inodos diferentes
    6. Como consecuencia de lo anterior, en esta configuración volvemos a gastar 3K: 1K para el directorio, 1K para la carta en sí y 1K para el enlace blando
    ¡Pues vaya un negocio que hemos hecho! A pesar de todo esto, los administradores suelen usar mucho más los enlaces blandos que los duros.

    La exposición anterior está simplificada para que se entienda mejor. En realidad, en los inodos no se encuentran directamente los datos, sino referencias a ellos. Además, en los inodos se encuentra toda la información adicional del fichero salvo, claro está, su nombre, que se encontrará en su(s) entrada(s) de directorio.

    Salvo las entradas . y .., no está permitido hacer enlaces duros a directorios. Enlaces blandos sí se pueden hacer.

    Una de las ventajas, que no se comentan, de los enlaces blandos frente a los duros es que los enlaces duros no se pueden establecer entre diferentes sistemas de ficheros. Por ejemplo, si tenéis dos discos duros en vuestro ordenador, no podéis formar un enlace duro entre un fichero de uno y otro fichero del otro. La razón es que los números de inodo son propios de cada sistema de ficheros.
  11. Ejercicio

    Cread enlaces duros y simbólicos a ficheros y responded a las siguientes preguntas, razonando la respuesta. Comprobad en el ordenador si habéis acertado con vuestros pronósticos:
    1. ¿Qué ocurre si borramos el origen de un enlace e intentamos acceder al destino?
    2. ¿Qué ocurre si borramos el destino de un enlace e intentamos acceder al origen?
    3. ¿Qué ocurre si hacemos un enlace, editamos una de las partes y accedemos a la otra?
    4. ¿Qué ocurre si hacemos un enlace, cambiamos los permisos de una de las partes y miramos los permisos de la otra?
  12. Búsqueda de ficheros o directorios

    La orden más estándar y antigua para localizar un fichero o directorio en el disco duro es find. Por ejemplo, si no recordamos dónde pusimos nuestra carta a los Reyes Magos, le podemos pedir al ordenador que nos la busque:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ find . -name ReyesMagos.txt -print
    find: cannot read dir ./PRUEBA: Permission denied
    ./CARTAS/ReyesMagos.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo$ ls -ld PRUEBA
    d---r-xrwx   2 gyermo   profes       512 ago 18 02:24 PRUEBA
    
    Nos ha dado un error, porque no puede entrar en el directorio PRUEBA, lo que no es de extrañar, pues recordad que en una de las sesiones le cambiamos los permisos, quitándonos todos, como se puede ver en el ls posterior.

    Lo bueno de find es que admite expresiones regulares como nombre. Pero debéis tener cuidado. Mirad el resultado de esta prueba, cuyo objetivo era encontrar el fichero SantaClaus.txt, pidiendo todos aquellos que empiezan por S mayúscula:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ find . -name S* -print
    find: bad option SESION6
    find: [-H | -L] path-list predicate-list
    <gyermo@ENCINA>/usuarios/profes/gyermo$ ls
    ARGUMENTOS                    MANTEJO
    backup                        PRIVADO
    bin                           PRUEBA
    CAJAFUERTE                    public_html
    CARTAS                        SESION3
    chgrp.2                       SESION6
    gyermo-encina-2005-03.tar.gz  TEMP
    mail
    
    ¿Os dais cuenta de por qué falla? Como hemos explicado un poco más arriba, antes de que find siquiera llegue a empezar, el ordenador ya ha sustituido las expresiones regulares que encuentre. Resulta que S* es una expresión regular que tiene dos coincidencias: SESION3 y SESION6. Después de hacer las sustituciones, lo que recibe find es:
    find . -name SESION3 SESION6 -print
    
    Entiende que queremos buscar un fichero o directorio que se llame SESION3 y no entiende qué pinta allí SESION6 y da el error. Para que haga lo que queremos, debemos proteger la expresión regular con cualquiera de los métodos que hemos visto:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ find . -name "S*" -print
    ./SESION3
    ./SESION6
    ./PRIVADO/SUTURNO
    ./PRIVADO/SUTURNO/SuTurno.log
    ./PRIVADO/SuTurno.log
    find: cannot read dir ./PRUEBA: Permission denied
    ./CARTAS/SantaClaus.txt
    
    find, junto con ls es una de las órdenes que más opciones tiene. Se pueden buscar ficheros no solamente por el nombre, sino por tamaño, fecha, tipo, etc. y con los ficheros encontrados no solamente se puede imprimir su ruta -print, sino, por ejemplo, ejecutar cualquier otra orden sobre ellos. Esto, cuando conozcamos alguna orden más, nos va a permitir realizar búsquedas basándonos en el contenido de los ficheros. Por último, no es necesario partir del directorio actual (.); se puede usar cualquier otro. Para más detalles, consultad, como siempre, la página de manual.

    En los últimos tiempos, se ha puesto de moda las herramientas que indizan el contenido de vuestro disco duro (es decir, almacenan de cuando en cuando, en una base de datos, los ficheros que tenéis en él). Si no os importa el espacio que gasta la base de datos, la sobrecarga de CPU cada vez que se actualiza la base de datos y que los nombres de vuestros ficheros anden por ahí en el disco duro, podéis echar un vistazo a la orden mlocate de vuestros linux. Si no os funciona, probad con locate a secas. Si no, es que el paquete no está instalado. La ventaja de estas herramientas es que la búsqueda es casi instantánea.
  13. Ejercicio

    En una carpeta situada bien dentro del directorio /usuarios/profes/gyermo/CAJAFUERTE se encuentra un fichero secreto de nombre desconocido. Vuestra misión es, valiéndoos de los medios conocidos hasta ahora, incluso consultando las páginas de manual si es necesario, que lo localicéis.
  14. Comparación de ficheros

    En algunas ocasiones nos interesa saber si dos ficheros son iguales. Tenemos dos órdenes a nuestra disposición: cmp y diff. La primera de ellas devuelve 0 en el caso de que los ficheros sean iguales, 1, si son diferentes y un número mayor, en el caso de haber un error. También imprime el lugar en que se diferencian.

    La segunda de ella es un poco más compleja. Está enfocada a encontrar diferencias entre versiones de un mismo fichero de texto plano, como puede ser un programa en C. El formato de la salida nos muestra, un tanto codificadas, cuáles son las diferencias entre los dos ficheros. Veamos, primero, un ejemplo de coincidencia:
    <gyermo@ENCINA>/usuarios/profes/gyermo$ cd CARTAS
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ ls
    ReyesMagos.txt  SantaClaus.txt
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ cmp *
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ echo $?
    0
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ diff *
    <gyermo@ENCINA>/usuarios/profes/gyermo/CARTAS$ echo $?
    0
    
    Veamos, ahora, a diff en su salsa. Que nos compare las dos versiones del programa en C que hicimos en la sección de interfaz con C de más arriba.
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ ls -l
    total 18
    -rwxr-xr-x   1 gyermo   profes      6552 ago 21 16:21 argumentos
    -rw-r--r--   1 gyermo   profes       291 ago 22 20:01 argumentos_viejo.c
    -rw-r--r--   1 gyermo   profes       414 ago 21 16:21 argumentos.c
    <gyermo@ENCINA>/usuarios/profes/gyermo/ARGUMENTOS$ diff argumentos_viejo.c argumentos.c
    3,4c3,4
    < int main(int argc,char *argv[])
    <  {int i;
    ---
    > int main(int argc,char *argv[],char *environ[])
    >  {int i; char **cpp;
    5a6,8
    >   for (cpp=environ; *cpp!=NULL; ++cpp)
    >     fprintf(stderr,"Variable de entorno: %s\n", *cpp);
    > 
    
    Traducido a palabras que todos podamos entender, diff nos dice que, para transformar un fichero en otro, hay que cambiar las líneas 3 y 4 del primero por las 3 y 4 del segundo y hay que añadir al primero (y por tanto quitar al segundo) en la línea 5 las líneas de la 6 a la 8 del segundo.
  15. Órdenes de la shell relacionadas.

    echo
    imprime en la pantalla sus argumentos
    unset
    desdefine una variable
    which
    muestra la orden del fichero que se ejecuta con una orden
    set
    muestra las variables de entorno
    find
    busca ficheros o directorios
    cmp
    compara dos ficheros
    diff
    compara dos ficheros de texto, mostrando las diferencias
    cp
    copia de ficheros
    mv
    mueve o renombra un fichero
    rm
    borra un fichero
    du
    muestra lo que ocupa un directorio y su contenido en el disco
    ln
    construye un enlace duro o blando


  16. Funciones de biblioteca relacionadas.



  17. LPEs.


© 2022 Guillermo González Talaván.