\documentclass[a4paper, 12pt]{article}

%
% Apunte curso inicial de GNU/Linux
% Copyright (C) 2008  Maximiliano Curia y Margarita Manterola
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.
%

\usepackage{ucs}
\usepackage[utf8x]{inputenc}
\usepackage[spanish]{babel}

\addtolength{\oddsidemargin}{-.875in}
\addtolength{\evensidemargin}{-.875in}
\addtolength{\textwidth}{1.75in}
\addtolength{\topmargin}{-.875in}
\addtolength{\textheight}{1.75in}

\title{Curso de GNU/Linux para principiantes}
\author{Margarita Manterola \and Maximiliano Curia}
\date{Facultad de Ingeniería - UBA \\ Actualizado Octubre 2004}

\begin{document}

\maketitle

%\tableofcontents

%\newpage

\section{Conociendo GNU/Linux}

GNU/Linux es un sistema operativo derivado de UNIX, que se distribuye en forma
libre.

\subsection{Qué es UNIX}

UNIX es un sistema operativo multitarea, multiusuario, creado en 1969 por
los investigadores Thompson y Ritchie de los Laboratorios Bell, en los
Estados Unidos.  Las primeras versiones fueron escritas en assembler, pero muy
pronto fue re-escrito en lenguaje C.

En sus primeros años, no se lo utilizó comercialmente, sino que se lo
usaba para proyectos de investigación en laboratorios
y se distribuía gratuitamente en las universidades, donde tuvo mucha
aceptación.

En 1975, Bell decidió comercializarlo.  Dado que el sistema se vendía con
una licencia que permitía modificarlo y redistribuirlo, a lo largo del tiempo
fueron surgiendo una gran variedad de sistemas derivados del UNIX original.  
Los más conocidos, actualmente, son: Solaris, AIX, HPUX, SCO, BSD.

Por esta razón, varias veces se hizo necesario normalizar estos sistemas,
para que cumplan con determinadas normas (POSIX, UNIX95, etc), para permitir
la compatibilidad entre los diferentes sistemas.

De estas normas, el sistema operativo GNU/Linux satisface la norma POSIX-1, y
casi completamente la POSIX-2.

\subsection{Qué es GNU}

La sigla GNU significa {\it GNU is Not Unix}.

En 1984, Richard Stallman fundó el Proyecto GNU con el objetivo de 
conseguir un sistema operativo libre y abierto. Esto es, un sistema
operativo tal que los usuarios puedan usarlo,
leer el código fuente, modificarlo, y redistribuirlo.

A partir de ese momento, un gran número de colaboradores se fueron sumando
al proyecto, desarrollando software libre para reemplazar cada una de las
herramientas del sistema UNIX. 

La filosofía GNU apoya el crecimiento de la sociedad como un conjunto,
haciendo especial hincapié en la valoración de las libertades personales,
aún cuando esto puede estar en conflicto con intereses empresariales.

\subsection{Qué es Linux}

En 1991, Linus Torvalds completó el sistema con su kernel (que es la
aplicación encargada de comunicar los procesos con el hardware de la 
computadora).  A este kernel lo bautizó Linux.

De esta manera, se formó el sistema GNU/Linux.

\subsection{Qué es BSD}

La Universidad de Berkeley estuvo relacionada con el desarrollo de los sistemas
operativos UNIX.  Recibió de AT\&T una versión gratuita de UNIX, y a partir de
entonces comenzó a promover el desarrollo de aplicaciones para UNIX dentro de la
universidad.

Mas adelante, desarrollo su propio sistema operativo UNIX, sin utilizar el
código fuente de AT\&T.  El kernel fue creado desde Berkeley, pero las
herramientas utilizadas son en su mayoría GNU, es decir las mismas que en el
sistema GNU/Linux.

Existen actualmente 3 sistemas operativos libres, derivado de BSD: FreeBSD,
OpenBSD y NetBSD.


\subsection{Qué es X}

El sistema operativo GNU/Linux cuenta con una interfaz gráfica, llamada 
XFree86 o simplemente X.

El protocolo X fue desarrollado por el MIT, principalmente como un logro
académico para proporcionar un entorno gráfico a UNIX.  La licencia
mediante la cual se distribuye permite usarlo, modificarlo, redistribuirlo
e incluso re-licenciarlo.

\subsection{Qué son las distribuciones}

El código fuente del sistema GNU y del kernel Linux está accesible a todo
el mundo, sin embargo, hacer funcionar un sistema a partir del código fuente
es bastante difícil.  Por eso, un sistema operativo se distribuye
(normalmente) en formato binario, es decir {\bf ya compilado}.

Poco después de que apareciera el kernel Linux, comenzaron a aparecer las
primeras distribuciones, que agrupaban versiones probadas de varios programas,
junto con el kernel, de tal manera que formaban un sistema operativo listo para
usar.

A medida que fue pasando el tiempo, algunas distribuciones se fueron haciendo
más sofisticadas, otras desaparecieron, otras se hicieron comerciales y
aparecieron mucha más.  Existen distribuciones de muchos tipos: distribuciones
que ocupan 1 diskette y distribuciones que llegan a ocupar 10 CDs;
distribuciones orientadas a una finalidad en especial (redes, seguridad,
etc) y distribuciones de uso general.

Cada usuario de GNU/Linux suele elegir la distribución con la que se siente
más cómodo, y no tiene sentido entrar en discusiones acerca de cuál es
mejor.

A menos que aclaremos lo contrario, lo que se enseña en este curso es
aplicable a la gran mayoría de los sistemas UNIX, y a cualquiera de las
distribuciones de GNU/Linux.

\subsection{Qué son las plataformas}

El mundo de las computadoras no se restringe a las Computadoras Personales
con las que estamos en contacto todos los días.  Existen
diversas arquitecturas en las que una computadora se puede presentar.  A cada
una de estas arquitecturas la llamamos {\it plataforma}.

Ejemplos de algunas plataformas posibles son: iMac (de
Macintosh), Sparc (de Sun), S/390 (de IBM), PlayStation (de Sony), XBox (de
Microsoft).

En particular, la plataforma que utilizamos comúnmente se la denomina {\it
i386}, ya que está basada en los procesadores de Intel, a partir del 386.

\subsection{Por qué aprender acerca de GNU/Linux}

Actualmente, a partir de la popularización de Internet, ha crecido en gran
medida la cantidad de servidores de red en todo el mundo.  Estos servidores 
deben contar con un sistema confiable, que pueda ofrecer los servicios de
correo, web, etc.  Por eso es que la gran mayoría de estos servidores
utilizan algún derivado de UNIX como sistema operativo.

Dado que el sistema GNU/Linux cumple muy bien con estas características, 
con el adicional de que se puede obtener completamente gratis, 
año a año ha crecido el número de servidores que lo utilizan.

En el caso de las computadoras personales, a partir de la aparición de más y
más aplicaciones gráficas, de uso general en el sistema GNU/Linux, se ha
hecho posible la utilización de este sistema para computadoras de escritorio.
La gran cantidad de software desarrollado en todo el mundo, permite tener muy
buena compatibilidad con otras computadoras, y tener disponibles -al mismo
tiempo- las herramientas UNIX.

\subsection{Software Libre}

A lo largo de todo este curso, siempre utilizamos Software Libre.  Por lo
general, este software lo hemos obtenido gratuitamente, sin embargo,
debemos entender que el hecho de que el software sea libre está
relacionado {\bf con la libertad} que nos otorga a los usuarios de
utilizarlo, modificarlo y distribuirlo, {\bf no con el
precio} al cual lo podemos obtener.

Al hablar de software libre se suelen clasificar los distintos grados de
libertad a los que podemos tener acceso los usuarios.

\begin{description}
\item[Libertad Grado 0]
        El software se puede {\bf usar}.
        Es la libertad que nos otorga casi cualquier software.

\item[Libertad Grado 1]
        El software se puede {\bf modificar}.  Es decir, se puede personalizar,
        mejorar, adaptar para las necesidades particulares de un determinado
        usuario.
\item[Libertad Grado 2]
        El software se puede {\bf distribuir}.  Es decir, se puede copiar, vender,
        prestar o compartir a las personas que el usuario desee, sin tener que
        pedir permiso al autor del software.
\item[Libertad Grado 3]
        El software se puede {\bf distribuir modificado}.  Se trata de una suma de
        la 1 y la 2.  Permite que las mejoras que un usuario le haya hecho a un
        determinado software puedan compartirse con otros usuarios.
\end{description}

Para poder considerar que una determinada aplicación cumple con los
requisitos de software libre es necesario que estén dadas estas
cuatro libertades para {\bf cualquier} usuario.

En particular para poder tener la libertad de modificar el software,
es necesario tener acceso al código fuente del programa en
cuestión, y no solamente al código binario (llamamos código
binario a aquél que es entendido por la computadora) ya que para
poder modificar correctamente el software es necesario poder acceder
al código fuente original. \\

Estas ideas de software libre como las conocemos hoy fueron desarrolladas y
trabajadas durante mucho tiempo por Richard Stallman y sus seguidores,
miembros de la ``Free Software Fundation'' (Fundación del Software
Libre).

En general las ideas del software libre buscan promover la
generación de mejor software (a través de la suma de los
pequeños aportes de cada persona), y colaborar para que toda la
sociedad se vea beneficiada con los avances del software. Es decir,
logramos mejorar la sociedad al tener disponibles más y mejores
herramientas.

Para más información sobre el software libre pueden visitar el sitio
de internet del Proyecto GNU (http://www.gnu.org), que tiene una gran cantidad
de documentos relacionados con la filosofía del software libre.

\newpage

\section{Conceptos Generales}

\subsection{Modo Gráfico - Modo Consola}

Como ya dijimos anteriormente, GNU/Linux puede utilizar el {\it Modo
Gráfico}, si utiliza la aplicación XFree86.

Por otro lado, llamamos {\it Modo Consola}, al modo que es puramente texto.
Gran cantidad de los temas que se enseñan en este curso se pueden probar en
modo consola, o bien en una consola gráfica, dentro del modo gráfico.

\subsection{Comenzando la sesión}

Dado que UNIX es un sistema multiusuario, para poder comenzar a utilizarlo
debemos ingresar el usuario y password que nos identifica.  Esto lo podemos
hacer tanto en modo gráfico como en modo consola.

Muchas veces, cuando ingresemos nuestra contraseña a un sistema UNIX, no
veremos los caracteres (ni siquiera un '*').  Esto se debe a que de esta
manera es más difícil que un observador sepa la cantidad de caracteres que
contiene nuestra contraseña. \\

Una vez que hayamos ingresado, tendremos acceso a nuestros archivos, y podremos
ejecutar una gran cantidad de aplicaciones, según los permisos que se le
hayan dado a nuestro usuario. 

Es decir que, cada usuario que utilice el sistema tendrá un tratamiento
distinto.  A esto nos referimos cuando decimos que todo sistema derivado de
UNIX es {\bf multiusuario}. \\

En particular, existe un usuario que es el encargado de administrar el
sistema, es el usuario que tiene acceso a los archivos de configuración, a
instalar y desinstalar el sistema.  Este usuario suele tener el nombre de {\it
root}, o también {\it superusuario}.


\subsection{Permisos y propiedad}

En GNU/Linux los permisos sobre los programas y los archivos del sistema son
bastante más específicos que en sistemas como Windows.
Existen los conceptos de {\bf propiedad} y {\bf permisos}.

Propiedad: los usuarios son propietarios de archivos.
Todos los archivos que un usuario crea son su propiedad.

Permisos: se refiere a lo que un usuario puede hacer con un determinado archivo,
sea o no el dueño de ese archivo.  Mediante los permisos, se controla quién 
puede visualizar, editar o ejecutar archivos en el sistema.

\subsection{Consolas virtuales}

En GNU/Linux y en sistemas UNIX modernos en general, es normal que nuestra
computadora funcione como muchas terminales a un mismo tiempo.  
En un sistema UNIX tradicional, por otro lado, cada estación de
trabajo nos daría acceso a una única terminal del sistema.

A esta característica que nos permite tener varias terminales en una sola
computadora, la llamamos {\it consolas virtuales}.

Para cambiar de una terminal a otra, normalmente se utiliza la combinación de
teclas {\bf Alt-F1}, {\bf Alt-F2}, etc.  O bien, {\bf Ctrl-Alt-F1}, 
{\bf Ctrl-Alt-F2}, etc.

Dentro de una consola podemos movernos hacia arriba o hacia abajo, utilizando
la combinación de teclas {\bf Shift-PgUp} y {\bf Shift-PgDn}.

\subsection{Apagado del sistema}

Como en otros sistemas operativos, es importante ejecutar un comando que
cierre todas aquellas aplicaciones que estén corriendo, antes de apagar el
sistema.  En caso contrario, al reiniciar el sistema operativo se efectuará
una verificación del disco rígido.

A diferencia de otros sistemas operativos, los sistemas UNIX están pensados
para permanecer encendidos constantemente, esto hace que los usuarios comunes
(los que no son el superusuario) no puedan apagar el sistema en forma remota.

En consecuencia, cuando solamente tenemos acceso de nivel usuario a una
computadora con un sistema UNIX, la única manera de apagarla en forma segura
es haciendo {\bf Ctrl-Alt-Del} desde modo consola.  Una vez presionada esta
combinación de teclas, todos los procesos que se estén ejecutando serán
detenidos, y la computadora se reiniciará.

En cambio, si fuéramos el superusuario del sistema, podremos ejecutar los
comandos \verb!halt! o \verb!reboot! para apagar o reiniciar el sistema,
respectivamente.


\section{Recorrido por el sistema}

Vamos a ver algunos comandos básicos de todo UNIX, que nos permitirán
familiarizarnos con el sistema.  Para poder utilizar estos comandos ya debemos
haber iniciado la sesión.

Cuando hemos iniciado la sesión estaremos delante de un {\it prompt}
(solicitud), que es la línea de comandos de UNIX.  El formato de
este prompt será similar a: \verb!user@anteojito:~$!. \\  %$

La mayoría de estos comandos son herramientas simples, que realizan una sola
tarea.  Más adelante aprenderemos como combinar lo que hacen dos o más
herramientas para lograr un resultado más interesante.

Algunos de estos comandos pueden recibir opciones o parámetros, que
pueden hacerlos realizar tareas diferentes.  En UNIX, casi todas las
opciones que reciba un comando estarán precedidas por el caracter
\verb!-!, y pueden combinarse según sea necesario. \\

Es importante notar que UNIX es sensible a las mayúsculas y
minúsculas ({\it case sensitive}), de forma que si queremos
obtener la salida correcta es necesario escribir los comandos que
aquí se explican tal cual se presentan (casi siempre en
minúsculas).

\subsection{Comandos Sencillos}

\subsubsection{date}

Ejecutando el comando \verb!date! obtendremos la fecha y
la hora actual. También es el comando que se usa para cambiar la
fecha de la máquina.

\subsubsection{who}
El comando \verb!who! nos permite ver los usuarios que están
utilizando el sistema, incluyendo la fecha en la que se conectaron al
sistema.

Además, una versión alternativa (\verb!who am i!) nos
muestra únicamente nuestra conexión.

\subsubsection{uptime}

Podemos ver cuánto tiempo hace que se ha iniciado el sistema de
nuestra computadora ejecutando el comando \verb!uptime!.  También
obtendremos alguna información adicional, como la cantidad de
usuarios que están utilizando el sistema, o la carga promedio que
tiene el procesador.

\subsubsection{clear}

El comando \verb!clear! sirve para limpiar la pantalla. Es
equivalente al \verb!cls! de DOS.

\subsubsection{echo}

\verb!echo! es un comando muy sencillo.  Lo que hace es
repetir todo lo que recibe por línea de comandos.  Si ejecutamos:
\verb!echo Hola! obtendremos la salida \verb!Hola!.

A pesar de parecer inútil, este comando nos será de bastante
utilidad cuando aprendamos más sobre el intérprete de comandos del
sistema.

\subsection{Comandos relacionados con archivos y directorios}

\subsubsection{pwd}

El comando \verb!pwd! es muy sencillo, nos
muestra la ruta de directorios en la que estamos situados en este
momento. Por ejemplo, {\bf /home/user}.

\subsubsection{ls}
Para listar los archivos dentro de un determinado directorio
utilizaremos el comando \verb!ls!. El equivalente en DOS es 'dir'.

Si ejecutamos \verb!ls! sin ninguna opción, nos listará los
archivos del directorio actual.  Si, en cambio, ejecutamos
\verb!ls directorio!, nos listará los archivos de ese
directorio.

Puede recibir varias opciones:

\begin{itemize}
\item \verb!-l!: muestra mucha más información sobre los archivos,
como el usuario y el grupo al que pertenece, el tamaño, los
permisos, etc.
\item \verb!-a!: muestra todos los archivos, incluyendo los ocultos.
\item \verb!-t!: ordena los archivos por fecha de modificación.
\end{itemize}

Estas opciones pueden combinarse, utilizando un solo signo '-', por ejemplo:
\verb!ls -lat!.

\subsubsection{touch}

El comando \verb!touch archivo! puede tener dos
consecuencias: si \verb!archivo! no existe aún, lo crea con tamaño
0 y como propiedad de nuestro usuario.  Por otro lado, si
\verb!archivo! ya existe, actualiza la fecha de modificación.

\subsubsection{cp}

El comando \verb!cp! es el que se utiliza para copiar archivos.

Si escribimos \verb!cp viejo nuevo!, copiaremos el archivo
\verb!viejo! con el nombre \verb!nuevo!.  Es decir, el archivo
origen se escribe primero y a continuación el archivo que se va a
crear. Una vez hecha la copia, tendremos dos archivos diferentes, con
el mismo contenido.

Por otro lado, también podemos ejecutar 
\verb!cp archivo1 archivo2 directorio!, 
de forma que los archivos \verb!archivo1! y
\verb!archivo2! se copiarán dentro de \verb!directorio!.

\subsubsection{mv}

Muy similar a \verb!cp!, el comando \verb!mv! es el que se utiliza para mover
archivos de un lugar a otro, o para cambiarle el nombre a un archivo.  Si
ejecutamos, \verb!mv viejo nuevo!, el archivo \verb!viejo! habrá pasado a
llamarse \verb!nuevo!.

Por otro lado, si ejecutamos \verb!mv archivo1 archivo2 directorio!, los
archivos \verb!archivo1! y \verb!archivo2! se moverán dentro de
\verb!directorio!.

\subsubsection{rm}

Para borrar archivos utilizamos el comando \verb!rm!.  Hay que usarlo
cuidadosamente, porque una vez que los archivos han sido borrados, no pueden
recuperarse {\bf de ninguna forma}.

Si deseamos que \verb!rm! nos pregunte si queremos borrar o no un archivo,
debemos utilizar la opción \verb!-i!, mientras que si deseamos que no nos
pregunte utilizamos la opción \verb!-f!.  Dependerá de la configuración
del sistema cual de estas dos opciones es la que está seleccionada por
omisión.

\subsubsection{mkdir}

Utilizamos el comando \verb!mkdir directorio! para crear directorios.  Pueden
utilizarse rutas absolutas o relativas.  Es decir que si queremos crear el
directorio \verb!/home/user/temp!, y estamos situados dentro del directorio
\verb!/home/user!, podremos ejecutar \verb!mkdir temp! o
\verb!mkdir /home/user/temp! indistintamente.

\subsubsection{rmdir}

Para borrar directorios utilizamos el comando \verb!rmdir directorio!.  
Solamente funcionará si el directorio está vacío.
En caso contrario, habrá que borrar primero los archivos, para luego borrar 
el directorio.

\subsubsection{cd}

El comando \verb!cd! nos permite cambiar de directorio, igual que en DOS. \\

Por ejemplo, \verb!cd /! nos lleva al directorio raíz, que es de donde
surgen todos los directorios del sistema.

Para cambiar a otro directorio dentro del árbol, podemos utilizar 
\verb!cd usr!, o \verb!cd /home/user!. Más adelante veremos 
cómo se organiza el
árbol de directorios, y qué hay en cada uno. \\

Utilizado sin ningún otro parámetro, \verb!cd! nos lleva al directorio
personal del usuario ({\it home}). Otra manera de ir al directorio personal es
utilizar \verb!cd ~!, ya que el símbolo \verb!~! identifica al directorio de
cada usuario.\\

Para cambiar al directorio padre del directorio actual se utiliza \verb!cd ..!
(no olvidar el espacio).  Mientras que para volver al directorio en el que nos
encontrábamos antes de ejecutar el último \verb!cd!, podemos ejecutar
\verb!cd -!.

\subsubsection{file}

En UNIX los archivos no se identifican por su extensión, como en DOS.  Se les
puede poner una extensión, pero es de adorno.

El comando \verb!file! nos permite tener una idea del contenido de un archivo.
Al ejecutar \verb!file archivo!, inspecciona partes del archivo para darse cuenta
qué clase de archivo es.  Puede decirnos que se trata de un archivo de texto,
un directorio, una imagen, etc.

\subsubsection{du}

El comando \verb!du!, {\it Disk Usage}, nos muestra el espacio que ocupan
todos los directorios a partir del directorio actual.  El número de la primera
columna es el espacio ocupado por el directorio y está expresado en kb. 

\begin{itemize}
\item \verb!du -s! nos muestra únicamente el total.

\item \verb!du -a! muestra lo que ocupan los archivos, además de los directorios.

\item \verb!du -h! hace el listado, indicando la unidad (human readable).

\item \verb!du archivo! nos dice cuánto ocupa el archivo.
\end{itemize}

\subsubsection{df}

El comando \verb!df!, {\it Disk Free}, nos muestra qué tan ocupados están los
discos del sistema. El parámetro \verb!-h!, al igual que en el caso del
comando \verb!du!, nos muestra las unidades en que se miden los numeros
presentados.

\subsubsection{find}

El comando \verb!find! permite encontrar archivos, utilizando diversas
técnicas.  En principio, si se le pasa como parámetro únicamente una
determinada ruta, por ejemplo \verb!find /home/user!, el comando buscará
todos los archivos y directorios que se encuentren a partir de esa ruta.

Utilizando algunos otros parámetros es posible buscar los archivos por
diversos criterios.

\begin{itemize}

\item \verb!find . -name "hola.txt"! encuentra todos los archivos llamados
\verb!hola.txt! que se encuentren a partir del directorio actual.  Las
comillas no son obligatorias, pero son recomendables si se quieren usar
opciones más complejas (por ejemplo, utilizando meta-caracteres de shell,
que se explican en la sección \ref{metacaracteres}).

\item \verb!find . -size 50k! busca los archivos que ocupan 50 kilobytes a
partir del directorio actual. Si se utiliza \verb!find . -size 20c!,
buscará los archivos que ocupen 20 bytes.  Y si se utiliza
\verb!find . -size 5b!, buscará los archivos que ocupen 5 bloques de 512
bytes cada uno.

\item \verb!find /home/user -empty! busca todos los archivos que se
encuentran vacíos, a partir del directorio \verb!/home/user!.

\end{itemize}

Es posible, además, utilizar opciones adicionales para la búsqueda, que
indiquen la profundidad de la búsqueda, que agreguen otros criterios
adicionales a los explicados, o que indiquen una acción a llevar a cabo una vez
encontrados los archivos.

\subsubsection{locate}

Otro comando que nos permite buscar archivos es \verb!locate!. Las busquedas de
\verb!locate! nos sirven para encontrar archivos en cualquier parte del
sistema, por ejemplo \verb!locate bash! nos va a mostrar todos los archivos y
directorios del sistema que en su nombre contienen la palabra {\bf bash}.

Las busquedas de \verb!locate! son mucho más rápidas que las de \verb!find!,
esto se debe a que utiliza una base de datos que contiene los nombres de los
archivos de todo el sistema. Esta base de datos no se actualiza
constantemente, por lo que \verb!locate! no encontrará los archivos recién
agregados al sistema e incluirá los recientemente removidos hasta que esta
base de actualice.

Para actualizar esta base de datos debemos ejecutar \verb!updatedb!, como
superusuario.  En las máquinas que están prendidas constantemente, este
programa se ejecuta una vez al día, durante la madrugada, de manera que la
base de datos permanece acualizada.

\subsubsection{cat}

Ejecutando \verb!cat archivo! podremos ver el contenido de
\verb!archivo!.  Este comando puede recibir una serie de archivos, y
el resultado será que nos mostrará un archivo a continuación del
otro.

Un caso especial se produce cuando ejecutamos \verb!cat! sin ningún nombre
de archivo.  En este caso, el comando esperará a que nosotros le demos una
entrada, y la irá reproduciendo línea por línea.  Hasta que presionemos
la combinación {\bf Ctrl-d}, que indica que la entrada ha terminado.

\subsubsection{od}

El comando \verb!od! {\it Octal Dump}, nos permite ver byte a byte el
contenido de un archivo.  La primera columna es la dirección de cada línea
que vemos. Utilizando las distintas opciones, podemos
visualizarlo en varios formatos: 

\begin{itemize}
\item \verb!od archivo! nos muestra el contenido del archivo expresado en
números octales, generalmente tomados de a dos bytes.
\item \verb!od -b archivo! nos muestra el contenido, en números octales, byte a byte.
\item \verb!od -c archivo! nos muestra los caracteres que forman el archivo,
uno por uno.
\item \verb!od -cb archivo! nos muestra los caracteres, y debajo de cada
caracter el número octal del byte.
\item \verb!od -h archivo! nos muestra el contenido, en números hexadecimales,
tomados de a dos bytes.
\end{itemize}

Las nuevas versiones de \verb!od! soportan muchos más formatos, utilizando la
opción \verb! -t formato!.


\subsubsection{wc}

El comando \verb!wc archivo!, se utiliza para contar la cantidad de líneas,
palabras y letras que tiene un archivo.

\subsubsection{less}

El comando \verb!less! permite paginar la salida de otros comandos, o bien, el
contenido de algún archivo.

Si ejecutamos \verb!less archivo!, veremos la primera página del archivo.
Si este archivo es lo suficientemente largo, podremos movernos hacia abajo y
hacia arriba utilizando PageUp, PageDown, Home, End, Enter, los cursores, la
barra espaciadora, etc.

También podemos realizar búsquedas dentro del archivo, para ello
utilizamos la barra \verb!/!, seguida del patrón que queremos
buscar.  Por ejemplo, si tipeamos \verb!/consola!, nos mostrará la primera
ocurrencia del patrón \verb!consola!.  Para ver la siguiente ocurrencia,
utilizamos \verb!n!, y para ver la ocurrencia anterior \verb!N!.

Para salir, utilizamos \verb!q!.

\subsection{Comandos relacionados con procesos}

Cada aplicación que se ejecuta dentro de un sistema UNIX es un proceso.
Algunos procesos están ejecutándose sin que nosotros lo sepamos.  Otros
procesos comienzan a ejecutarse cuando nosotros se lo indicamos.  

Cada proceso que se ejecuta dentro de nuestra computadora tiene un número
que lo identifica, llamado {\it Process ID} (PID). Este número será el que
deberemos utilizar para referirnos a ese proceso con otros comandos.

Vemos a continuación los comandos básicos para manejar procesos dentro de
los sistemas UNIX.

\subsubsection{top}

El comando \verb!top! nos muestra algunos de los procesos que se están
ejecutando, ordenados por el tiempo de procesador de la computadora que
consumen.  Muestra algunos datos adicionales de cada proceso, por ejemplo, en
la primera columna, podemos observar el PID de cada uno.

Además, muestra otros datos acerca del uso que se le esta dando a la
máquina.

Para salir: q.

\subsubsection{ps}

El comando \verb!ps! nos muestra la lista de procesos que se están
ejecutando en la computadora.  En particular, es interesante ver la salida de
\verb!ps ax!, que nos muestra todos los procesos, tanto los de nuestro usuario
como los de otros, e incluso los procesos que no tienen usuario.

La primera columna de la salida de \verb!ps! también contiene 
el PID del proceso.

\subsubsection{Ctrl-z}

La combinación de teclas {\bf Ctrl-z} sirve para suspender una tarea dentro
de su ejecución.

Por ejemplo, si estamos ejecutando el proceso \verb!top! y presionamos {\bf
Ctrl-z}, se suspenderá la ejecución de \verb!top! y volveremos a obtener
la línea de comandos.  Antes de devolvernos la línea de comandos, nos
indicará cuál es el número de trabajo del proceso que hemos suspendido.

Podemos iniciar varias tareas distintas, y luego suspenderlas.  De forma que
el número de trabajo de las tareas suspendidas se va incrementando.

\subsubsection{bg - fg}

El comando \verb!bg! permite que el proceso que se halle suspendido, continúe
ejecutándose en {\it background} (de fondo).  Mientras que el comando
\verb!fg! permite que un proceso suspendido pase a {\it foreground} (a la
pantalla principal). Por ejemplo, \verb!find /usr -name nethack! busca dentro
de /usr (grande) un archivo llamado nethack, esto puede tomar una considerable
cantidad de tiempo, apretando \verb!Ctrl-z! y luego ejecutando \verb!bg!
conseguimos que se siga ejecutando de ``fondo'', mientras nosotros podemos
seguir usando la consola. Cabe aclarar que cuando find encuentre algo lo
imprimira en la pantalla.

\subsubsection{jobs}

Para poder ver qué comandos se están ejecutando en background y cuáles
han sido suspendidos (o detenidos), podemos utilizar el comando \verb!jobs!.

La lista que nos muestra este comando incluye el número de trabajo, que no
es el mismo que el PID, y podemos utilizar este identificador para decidir
cuál de las tareas pasar a foreground o background.

Por ejemplo: \verb!fg 1! pasa a foreground el trabajo número 1. Mientras
que \verb!bg 3! pasa a background el trabajo número 3.

\subsubsection{kill}

Este comando nos sirve para interrumpir la ejecución de un determinado
proceso.  El comando envía una señal al proceso por la cual (normalmente)
se cierra.

Podemos ejecutarlo teniendo en cuenta el PID del proceso. Por ejemplo:
\verb!kill 1234!, matará el proceso 1234.  O bien, teniendo en cuenta el
número de trabajo.  En ese caso: \verb!kill %2!, detendrá el trabajo
número 2.

\subsubsection{Ctrl-c}

Cuando una aplicación se está ejecutando en foreground, y deseamos
detenerla, podemos utilizar la combinación de teclas {\bf Ctrl-c}.

El uso de esta combinación es equivalente a ejecutar el comando \verb!kill!
con el número de proceso de la aplicación que estamos utilizando.

\subsection{Obteniendo más información}

En GNU/Linux existen muchísimos documentos de ayuda, manuales y HOWTOs, que
están pensados para que cualquier persona pueda encontrar información
sobre lo que está buscando.

\subsubsection{man}

Un comando muy importante es \verb!man!.  Este comando nos mostrará las hojas
del manual del programa que estamos queriendo buscar.

Por ejemplo, \verb!man date! nos mostrará el manual del comando \verb!date!,
que ya sabemos que sirve para ver y configurar la fecha, aquí está
explicado cómo utilizarlo.

Podemos movernos dentro de las páginas de los manuales utilizando la barra
espaciadora, Enter, los cursores y el mismo sistema de búsqueda que
utilizamos en \verb!less!.  Para salir, utilizamos \verb!q!.

\subsubsection{info}

Un comando muy similar a \verb!man!, es el comando \verb!info!.  Las páginas
que nos muestra este comando suelen tener una mayor cantidad de información
acerca de la aplicación sobre la cual estamos consultando.

Por ejemplo \verb!info sh-utils!, contiene información detallada sobre
algunas de las utilidades del intérprete de comandos ({\it shell}), que se
verá más adelante.

\subsubsection{help}

Algunos comandos (como \verb!fg!), son parte interna del intérprete de
comandos, y por esta razón no tienen una página del manual que los
explique.

Para saber de qué manera utilizar estos comandos, usamos \verb!help!.  La
ayuda que nos da este comando es más sintética que la de \verb!man!.

Por ejemplo \verb!help jobs!, nos informará sobre el uso del comando
\verb!jobs! visto anteriormente.

\subsubsection{Archivos con información}

Dentro del directorio \verb!/usr/share/doc!, encontramos una gran cantidad de
documentos que tratan las distintas aplicaciones que tenemos instaladas en
nuestro sistema.

En particular, el directorio \verb!/usr/share/doc/HOWTO!, contiene artículos
sobre cómo hacer determinadas cosas dentro de nuestro sistema.

\newpage

\section{Shell}

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

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

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

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

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

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

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

Además, completa los nombres de comandos y archivos automáticamente, al
presionar la tecla TAB.
\end{description}

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

\subsection{Meta-caracteres}
\label{metacaracteres}

Además de ejecutar los comandos que nosotros le indicamos, el shell interpreta
ciertos caracteres especiales, a estos caracteres los llamamos
me\-ta\-ca\-rac\-te\-res.

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

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

\subsubsection{Meta-caracteres relacionados con archivos}

\begin{tabular}{lp{12cm}}
\verb!*! & Cuando el shell encuentra un \verb!*!, lo reemplaza por una lista de
los archivos que concuerdan con la expresión indicada.  

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

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

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

Por ejemplo: \verb!echo ?ola! nos
podría mostrar archivos como \verb!hola!, \verb!sola!, \verb!Pola!. 
\verb!echo a??a!, podría mostrar \verb!allá!, \verb!arca!, \verb!Asia!.  

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

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

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

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

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

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

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

\end{tabular}

\subsubsection{Meta-caracteres relacionados con comandos}

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

\begin{description}
\item[;] El \verb!;! es un separador de comandos, nos permite ejecutar un
comando a continuación de otro, equivalente a lo que sucedería si
ejecutáramos primero uno, y al terminar ejecutáramos el siguiente.  

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

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

\item[\&] El \verb!&! manda el comando a background, esto quiere decir, que nos
devuelve la línea de comandos inmediatamente después de apretar Enter,
mientras el comando sigue ejecutándose en segundo plano. 

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

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

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

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

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

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

\end{description}

\subsubsection{Otros meta-caracteres}

\begin{description}

\item['...'] Al encontrar una cadena encerrada entre ' ', el shell tomará el
  contenido de la cadena literalmente, es decir, sin interpretar los
  meta-caracteres contenidos en ella.

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

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

\item[$\backslash$] Utilizamos una $\backslash$ para escapar el siguiente
  caracter.  Escapar significa que el shell no lo interpretará como un
  meta-caracter.

  Por ejemplo \verb!echo \*! nos mostrará un \verb!*!.

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

\end{description}

\subsubsection{Entrada y Salida}

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

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

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

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

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

\begin{description}

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

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

\end{description}

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

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

\subsubsection{Ejercicios}

\begin{enumerate}
\item Explicar en qué se diferencian \verb!ls *! y \verb!echo *!.
\item Explicar en qué se diferencian \verb!ls /! y \verb!echo /!.
\item Crear un archivo que contenga la cantidad de archivos en un directorio.
\item Crear dos archivos: \verb!a.txt!, que contenga \verb!hola!, y 
\verb!b.txt!, 
que contenga \verb!chau!.  Luego concatenarlos en un archivo \verb!ab.txt!.
\end{enumerate}

\section{Manejo de Archivos}

Una de las características de UNIX es que todo es un archivo.  Esto no es una
simplificación, el sistema representa los dispositivos (disco rígido, placa
de sonido, CDs, disqueteras, algunas conexiones de red, etc) 
que están conectados a él como archivos. 

Estos archivos están todos ubicados a partir del directorio raíz, a partir
del cual se abre un árbol de directorios.  Al directorio raíz se lo
identifica como {\bf /}.  Si hacemos \verb!ls /! veremos los directorios que se
abren a partir del raíz.

Una de las ventajas del manejo de archivos de UNIX es que los usuarios no
necesitan saber dónde está cada directorio.  Cuando hacemos \verb!ls /!
puede suceder que algunos directorios estén en el disco rígido de la PC,
otros estén en un servidor de la red, otros en algún otro servidor, y
nosotros no nos enteraremos.

Identificamos con el nombre de {\bf file-system} a una estructura jerárquica
de directorios y archivos.  Es decir, una determinada colección de archivos.
En un solo sistema UNIX pueden estar {\it montados} varios file-systems
diferentes.  Esto es, un solo sistema UNIX puede agrupar los archivos que
están almacenados en distintas particiones de un disco rígido, en una
disquetera, en un CD, etc.

El árbol de directorios que vemos a partir del directorio raíz, es la forma
en la que organizamos los archivos, no necesariamente el lugar donde los
archivos están ubicados físicamente.

\subsection{Montar y desmontar file-systems}

Utilizando el comando \verb!mount! veremos los file-systems que tengamos
montados.  La salida de este comando nos lista: la identificación del
file-system, el lugar en el árbol de directorios en el que está montado y el
tipo de file-system que constituye.  Además, entre paréntesis, podemos ver
los flags con los que se ha montado.

Cuando queremos leer de un diskette, deberemos montarlo, ya que el diskette
constituye una nueva estructura de archivos.  Podremos montar diskettes que
estén grabados en distintos formatos, por ejemplo msdos, ext2, etc.

Para montar el diskette utilizaremos \verb!mount /floppy!, ya que /floppy es el
directorio en el que está configurado que se debe montar el dispositivo de la
disquetera, como un tipo de file-system automático, es decir que detecta
automáticamente qué tipo de filesystem se tiene.

Es necesario desmontar el diskette antes de sacarlo, ya que -si no lo hacemos-
el sistema puede no
haber terminado de actualizar los cambios hechos al file-system del diskette.
Para desmontarlo utilizaremos el comando: \verb!umount /floppy!. \\

Otro comando relacionado con los file-systems que se encuentran montados en
el sistema es \verb!df!.  Este comando nos muestra el espacio que está
siendo utilizado y el que todavía está libre, en los file-systems que se
encuentren montados.

\subsection{Árbol de directorios}

Existen diferentes maneras de ordenar la información dentro de los
directorios.  Veremos un orden básico que la mayoría de las distribuciones
utilizan.

\begin{description}

\item[/bin] contiene los archivos ejecutables básicos del sistema.  Muchos de
estos comandos ya los usamos o los vamos a usar en el futuro.

En este directorio, por ejemplo, encontramos algunos de los comandos de
shell que nombramos.

\item[/dev] contiene los archivos que representan a dispositivos.  Los archivos
que se encuentran en este directorio están relacionados con periféricos de
la máquina, por ejemplo: /dev/fd0 es el archivo que representa la primera
disquetera, /dev/hda representa al primer disco rígido IDE, /dev/hda1 
representa la primera partición del primer disco rígido IDE, /dev/tty
representa la consola actual que se está usando.  Así: 
\verb!echo hola > /dev/tty! nos mostrará la misma salida que 
un simple \verb!echo hola!.

Estas identificaciones corresponden al sistema de archivos utilizado por las
distribuciones de GNU/Linux.  En otros sistemas UNIX (como BSD, Solaris, etc).
Las identificaciones serán distintas, pero las podremos encontrar en el mismo
directorio /dev.

Un dispositivo curioso es /dev/null.  Se trata de un dispositivo que borra todo
aquello que se mueva a él, como un agujero negro.  Otro dispositivo interesante
es /dev/random, que nos muestra ``basura random'', es decir cualquier tipo de
caracteres, generados al azar según los procesos que se estén ejecutando en la
máquina y la entrada del usuario.

\item[/etc] contiene los archivos de configuración del sistema y de muchos de
los programas instalados en el sistema.  Además, contiene los scripts de
inicio que se ejecutan cuando arranca la máquina.  Generalmente los archivos
que se encuentran en este directorio pueden ser editados sólo por el
administrador de la máquina, es decir el superusuario, normalmente llamado
``root''.

\item[/home] en este directorio se encuentran los directorios principales de los
usuarios.  En estos directorios los usuarios tienen permisos de leer, escribir y
ejecutar según deseen.  

\item[/lib] contiene las librerías necesarias para ejecutar los comandos que
se encuentran en /bin y /sbin.  Las librerías son rutinas que los programas
utilizan frecuentemente, y pueden ser compartidas por varios programas al mismo
tiempo.

Esto se debe a que las librerías no están incluidas dentro de los
programas, para que sea sencillo reusar el código, y aprovechar mejor el
espacio. 

En otros sistemas UNIX, las librerías pueden estar incluidas en los
comandos, con lo cual este directorio no es necesario.

\item[/sbin] contiene los archivos ejecutables que son necesarios para poder
administrar el sistema.  


\item[/usr] contiene archivos que serán utilizados una vez que el sistema ya
está funcionando.  No son imprescindibles para el funcionamiento del sistema.

Por dentro se subdivide nuevamente en un árbol muy parecido al del directorio
raíz.

Encontramos, además, directorios como {\bf src} (donde se suelen guardar los
archivos con el código fuente del sistema), {\bf games} (que tiene juegos), \
{\bf X11R6} (que contiene el sistema X), {\bf share} (que contiene archivos a
los que pueden acceder todos los programas y todos los usuarios). 

\end{description}

\subsection{Los archivos por dentro}

El contenido de un archivo común no es mas que una sucesión de bytes, pero
cómo está esta información almacenada y cómo accedemos a ella es más
interesante. Para tener una idea de cómo se guarda la información en los
sistemas UNIX veremos el manejo de {\it inodos}.  

\subsubsection{Inodos}

Un inodo contiene el tamaño de un archivo, las tres fechas relacionadas con
el archivo (modificación del contenido, acceso al contenido y modificación
del inodo), los permisos, el dueño, el grupo, el número de links, e
información sobre dónde están físicamente los datos (los bytes) del
archivo en el disco. 

Notemos que el nombre del archivo no está guardado en el inodo.

De esta forma, un directorio es simplemente un archivo que contiene
una lista de números de inodos y nombres de archivos. 

\subsubsection{Links}

Dentro del inodo se guarda el número 
de links del archivo.  Un link es una entrada en un directorio, es decir en la
lista de inodos y nombres de archivos.  Un archivo puede tener muchos links.
Esto significa que dos archivos con distinto nombre pueden apuntar a un mismo
inodo, y por lo tanto tener el mismo contenido.  Son el mismo archivo con dos
nombres diferentes. 

Es importante recalcar que una vez creado el link, es imposible decir cuál es
el nuevo archivo y cuál es el que ya estaba creado. Si borramos uno de estos
archivos, no se borrará el contenido del archivo, sino únicamente la entrada
de directorio, y se decrementará la cantidad de links al inodo.  Solamente
se eliminará el contenido del archivo cuando el número de links llegue a
cero. 

A este tipo de links se los llama {\it hard links}, existe otro tipo de links,
llamado {\it soft links} o también {\it symlinks} (Symbolic Link).  
Estos links no comparten el  inodo del otro archivo, ni
aumentan la cantidad de links que tiene el otro archivo, porque se trata
únicamente de un puntero a otro archivo, que se puede encontrar en cualquier
parte del sistema de archivos.  Es muy similar al {\it Acceso Directo} 
de Windows.

Dado que los datos de los inodos se guardan por separado en cada dispositivo (es
decir, partición de disco, CD, floppy, etc), no es posible crear {\it hard
links} entre dispositivos diferentes.  Sin embargo, sí es posible crear {\it
symlinks}.

\subsubsection{ln}

El comando \verb!ln! nos permite crear tanto {\it hard links} como 
{\it soft links}. 

Para crear un hard link deberemos escribir \verb!ln viejo nuevo!.  De tal
manera que \verb!nuevo! estará asignado al mismo inodo al que ya estaba asignado
\verb!viejo!.  Si hacemos \verb!ls -li! del directorio actual, podemos ver el
número de inodo en la primera columna, y el número de links en la tercera.
veremos que tanto \verb!viejo! como \verb!nuevo! 
tienen el mismo número de inodo y de links.

Para crear un {\it symlink} utilizamos \verb!ln -s viejo nuevo!.  
En este caso, al hacer \verb!ls -li! vemos que \verb!nuevo! tiene un 
inodo diferente a \verb!viejo!, y que
en el nombre aparece la ruta a la que apunta.

\subsection{Permisos}

Como ya dijimos antes, todos los archivos tienen un dueño y un grupo.  Para
ver el dueño y el grupo, podemos hacer \verb!ls -l!, la tercera columna es el
usuario y la cuarta el grupo.

Analizaremos la primera columna (que puede parecer un jeroglífico, pero
lo que nos indica es los permisos que tiene cada archivo).

El primer caracter nos indica qué tipo de archivo es.  Si tiene una 
\verb!"d"! es un directorio, si tiene una \verb!"l"! 
es un symlink, si tiene un \verb!"-"! es un archivo común.

Los siguientes tres caracteres indican los permisos que tiene el archivo para el
dueño.  La primera columna indica lectura, y puede tener una \verb!"r"! si
está habilitado el permiso o \verb!"-"! si no lo está.
La segunda indica permiso de escritura, y puede tener una 
\verb!"w"! si está habilitado o un \verb!"-"! si no lo está, la tercera indica
ejecución, y puede tener una \verb!"x"! si está habilitado o un \verb!"-"!
si no lo está.

Los otros tres caracteres son los permisos para el grupo, y los últimos tres
son los permisos para el resto de los usuarios. \\

En el caso de los directorios, el permiso de lectura significa que se 
puede listar el
contenido del directorio, haciendo -por ejemplo- \verb!echo dir/*!, 
el permiso de escritura significa 
que se pueden crear y borrar archivos en el directorio
y el permiso de ejecución significa que se pueden buscar archivos, 
hacer un \verb!cd!, etc. 

\subsubsection{chmod}

Para cambiar los permisos de un archivo utilizamos el comando \verb!chmod!.
Solamente el dueño de un archivo (o el administrador del sistema) puede
cambiarle los permisos a un archivo.  Aún si no tiene ninguno de los
permisos explicados, el dueño del archivo siempre tiene permiso de cambiar
los permisos de un archivo.

Hay dos maneras diferentes de utilizarlo.  Podemos sumar 
o restar permisos a los
que ya están, o bien configurar todos los permisos a la vez.

Si queremos sumar o restar determinados permisos, utilizamos la 
siguiente sintaxis: \\
\verb!chmod quien+que archivo!. donde \verb!"quien"! puede ser:
\verb!u! (usuario dueño), \verb!g! (grupo), \verb!o! (otros), o bien
\verb!a! (todos). Y \verb!"que"! puede ser \verb!r!, \verb!w! o \verb!x!.
Los permisos que no se agreguen ni quiten permanecerán como estaban.

Así, si escribimos \verb!chmod u+r archivo! le estamos agregando permiso 
de lectura al usuario.  Si hacemos \verb!chmod o-w archivo! le quitamos permiso
de lectura a los demás.  Por otro lado, escribiendo la línea
\verb!chmod a+x,go-w archivo! le
agregamos permiso de ejecución a todos los usuarios, y le quitamos el de
escritura a todos los que no son el dueño. \\

Por otro lado, existe una manera más rápida, pero también un poco más
complicada de cambiar los permisos.  Esta manera utiliza números octales.
Consideramos \verb!r = 4!, \verb!w = 2! y \verb!x = 1!.  
El valor del permiso que queremos 
asignar será la suma de los permisos.  Y lo tenemos que escribir para el
usuario, el grupo y los otros.

Ejemplo: \verb!chmod 644 archivo! asigna permisos de lectura y escritura para el
usuario y sólo de lectura para los demás.  \verb!chmod 755 archivo! asigna
permisos de lectura, escritura y ejecución al usuario y de lectura y
ejecución a los demás. \\

Si deseamos cambiar los permisos dentro de un directorio, de forma {\it
recursiva}, podemos utilizar la opción \verb!-R!.

\subsubsection{groups - chgrp}

Un usuario puede pertenecer a varios grupos.  Para ver a qué grupos
pertenece, utilizamos el comando \verb!groups!.

Y el comando \verb!chgrp grupo archivo! nos permite cambiar el grupo de un 
archivo.  Solamente podemos cambiar el grupo a otro grupo que también 
pertenezcamos.

\subsubsection{chown}

Este comando solamente lo puede ejecutar el superusuario, y le permite cambiar
el dueño de un archivo, pero como no tenemos permiso de superusuario, no
podemos utilizarlo.

\subsection{Ejercicios}

\begin{enumerate}
\item Indicar los comandos a utilizar para otorgarle a un archivo
cualquiera permisos de: \\
lectura y escritura solamente para el dueño del archivo; \\
lectura y ejecución para todos los usuarios; \\
lectura para todos los usuarios, y escritura solamente para el dueño del
archivo.
\item Crear un directorio (por ejemplo {\bf pruebadir}), y algunos archivos
dentro (por ejemplo, {\bf arch1 arch2 arch3}).  Cambiarle los permisos de
lectura, ejecución y escritura al directorio y probar diversos comandos:
\verb!echo prueba/*!, \verb!cd prueba!, \verb!touch prueba/arch4!,
\verb!rm prueba/arch3!, \verb!ls prueba!, etc.  De este modo se puede
apreciar qué significan realmente los permisos de lectura, escritura y
ejecución en un directorio.

\end{enumerate}

\newpage

\section{vi}

Vi es un editor de texto para consola.  Es el editor de texto tradicional de
UNIX, y en muchos sistemas es el único disponible, de manera que es importante
saber usarlo, aunque más no sea básicamente.

Para comenzar a editar un archivo deberemos escribir: \verb!vi archivo!, o bien
ejecutar \verb!vi!, y luego abrir el archivo con el comando adecuado.

En vi existen dos modos de trabajo: un modo de edición y un modo de comandos.  
Al
iniciar el programa, estamos en el modo de comandos.  Para ingresar al modo de
edición debemos apretar \verb!i!, o bien, {\bf Insert}.  
Para volver al modo de
comandos, utilizamos la tecla {\bf ESC}.  

Cuando estemos en el modo de
edición, todo lo que ingresemos será texto del archivo.  Cuando estemos en
el modo comandos, no.  A veces lo que escribamos no mostrará ninguna salida
inmediata en la pantalla. 

\subsection{Comandos Básicos}

\begin{tabular}{ll}
{\bf :e archivo} & abre el archivo. \\
{\bf :q} & sale del programa, solo si ya se grabaron los cambios. \\
{\bf :q!} & sale del programa sin grabar los cambios. \\
{\bf :w} & graba el archivo. \\
{\bf :w archivo} & graba el archivo con ese nombre (eq. Guardar Como) \\
{\bf :wq} & graba el archivo y luego sale del programa. \\
\end{tabular} \\

\subsection{Teclas de Movimientos}

\begin{tabular}{llc|cll}
{\bf 0} & inicio de línea. & & & {\bf \$} & fin de línea. \\
{\bf b} & anterior palabra. & & & {\bf w} & próxima palabra. \\
{\bf h} & izquierda. & & & {\bf l} & derecha. \\
{\bf k} & arriba. & & & {\bf j} & abajo. \\
{\bf G} & fin de archivo. & & & \\
\end{tabular} \\

A la mayoría de estos comandos se les puede agregar un número al 
principio.  El efecto de este número será el de multiplicar el efecto 
del comando por el número ingresado. Por ejemplo, {\bf 10j} se mueve 
10 lineas hacia abajo.

En el caso de {\bf G}, el número que se le agregue antes puede ser
el número de linea al cual deseamos ir.  Si deseamos ir a la primera
línea del archivo, debemos escribir {\bf 1G}.

\subsection{Manejo de Texto}

Como en cualquier editor de texto, podemos cortar, copiar y pegar. \\

\begin{tabular}{ll}
{\bf dd} & corta la línea. \\
{\bf dw} & corta la próxima palabra. \\
{\bf d\$} & corta hasta el final de la línea. \\
{\bf p} & pega lo que se haya cortado o copiado \\
{\bf u} & (undo) deshace la última acción. \\
{\bf yy} & copia la línea. \\
{\bf x} & corta el caracter. \\
\end{tabular} \\

Muchos de estos comandos también aceptan un número que los 
preceda, de tal manera que se pueden seleccionar varios caracteres, palabras o 
líneas a un mismo tiempo.

\subsection{Búsquedas}

Ingresando {\bf /texto}, (ENTER) nos llevará a la 
próxima aparición de 'texto'.
Para ir a la anterior: {\bf ?texto} (ENTER).
Una vez que lo hemos buscado, presionando {\bf n} iremos a la siguiente
aparición, y presionando {\bf N} iremos a la anterior.

\subsection{Otros}

\begin{tabular}{ll}
{\bf CTRL-g} & muestra la línea actual y el total de líneas. \\
{\bf o} & agrega una línea debajo de la actual, y entra en modo inserción.
\\
{\bf a} & se coloca en el caracter siguiente al actual, y en modo inserción.
\\
\end{tabular} \\ 

\subsection{Más información}

Dentro del mismo vi es posible obtener ayuda sobre cómo manejarlo,
utilizando el comando \verb!:help!, desde el modo comandos.  Para salir de
la ayuda y volver al archivo que se estaba editando: \verb!:q!.

Una de las versiones de vi más difundida es el vim (Vi Improved). Tiene 
muchas más características, como resaltado de sintaxis (syntax highlighting) y
muchas otras cosas más. Para los recién iniciados existe un comando
\verb!vimtutor!, que nos da unas breves clases sobre el uso de vim. 

\section{Emacs}

A pesar que emacs no se encuentra en todos los sistemas UNIX, y por lo tanto no
es una herramienta con la que podemos contar en cualquier caso, es uno de los
procesadores de texto más utilizados. En realidad es mucho más que un procesador
de texto, puede utilizarse como un lector de correo y de noticias, 
un navegador web, una interfaz para varios juegos, y hasta 
un entorno de programación y desarrollo. 

Esto es posible porque emacs es principalmente un intérprete del lenguaje 
LISP, un lenguaje que fue desarrollado para la investigación de inteligencia 
artificial. Dentro de emacs, es el intérprete de LISP 
quien ejecuta un editor de texto y el que interpreta cada uno de nuestras
entradas. Sin embargo, en esta introducción utilizaremos simplemente sus
capacidades como editor de texto.

\subsection{Una breve recorrida}

Para ejecutar emacs podemos, desde la línea de comandos escribir
\verb!emacs!, y dentro del emacs abrir el archivo que queramos editar. O
bien, abrir el archivo al entrar al emacs ejecutando \verb!emacs archivo!,
es posible, además, comenzar a editar varios archivos a la vez, utilizando
\verb!emacs arch1 arch2 arch3!.

Para abrir un archivo dentro de emacs, se utilizan las
teclas {\bf Ctrl-x Ctrl-f}. Esto muestra un mensaje en la parte inferior de
la pantalla \verb!Find file: ~/!, que indica que a continuación
puede ingresarse el nombre del archivo a editar. 
Al igual que dentro del intérprete de comandos \verb!bash!, 
la tecla \verb!TAB! nos será de gran utilidad,
ya que completará automáticamente el nombre del archivo, o desplegará 
una lista de los archivos que coincidan con el nombre que se escriba.

Una vez que hemos escrito lo
suficiente, se puede grabar utilizando {\bf Ctrl-x Ctrl-s}.

Para salir de emacs usamos las teclas {\bf Ctrl-x Ctrl-c}.
emacs preguntará si
queremos guardar los cambios hechos, contestando \verb!"y"! se grabarán los
cambios, mientras que \verb!"n"! no los grabará, y \verb?"!"? no guardará
ningún cambio.

\subsection{Meta y Control}

Emacs es un editor que no tiene múltiples modos como el vi. Es decir,
en cuanto se abre el editor ya está listo para que empieces a
escribir y todo lo que se escriba lo incluirá en el archivo que se está
editando.

Para acceder a un comando del editor debemos apretar una combinación
de teclas. Para eso usamos unas teclas denominadas Meta y Control
junto con otras teclas. Estas teclas no se muestran en el texto, son
órdenes al editor. La tecla Meta en la mayoría de las PCs modernas no
existe y en su reemplazo puede encontrarse la tecla ALT o la tecla
'windows'.

También es posible usar la tecla ESC como reemplazo de la tecla
Meta. Pero en ese caso la tecla ESC no es apretada al mismo tiempo que
la otra tecla, sino que apretamos primero la tecla ESC, la soltamos y luego
apretamos la tecla que dispare el comando o acción del editor.

Por ejemplo, para acceder al tutorial debemos apretar 
{\bf Ctrl-h t}, 
esto significa apretar la tecla Control al mismo tiempo que la
tecla h y luego la tecla t. Por comodidad, dentro de los tutoriales y
ayudas de emacs (y también dentro de esta breve introducción), se 
escriben estas combinaciones con una C para Control y una M para Meta.

\subsection{Ventanas (Buffers)}
\label{sec:buffers}

emacs es un editor que nos permite trabajar con múltiples archivos
a la vez. Cada archivo lo deja disponible a través de distintos
{\it buffers}, que son distintas ventanas a las que el usuario puede 
acceder; puede cambiar de una ventana a otra en cualquier
momento o tener varias ventanas de texto a la vista dentro de la misma pantalla
(dividiéndola al medio, en cuartos, en octavos, etc). 

Para obtener una lista de las distintas ventanas disponibles, podemos apretar
{\bf C-x b}, esto dividirá la pantalla actual en dos y en la
parte inferior tendremos una lista de todas las ventanas 
disponibles. Con {\bf C-x o} podemos pasar de la ventana superior a
la inferior, y viceversa.

A continuación, algunas otras teclas que pueden llegar a resultar 
útiles en el manejo de ventanas. \\

\begin{tabular}{ll}
{\bf C-x 2} & Divide la ventana actual en dos partes horizontales \\
{\bf C-x 3} & Divide la ventana actual en dos partes verticales \\
{\bf M-C-v} & Avanza una pantalla en la otra ventana \\
{\bf C-x o} & Cambia de ventana \\
{\bf C-x b} & Muestra una lista de todas las ventanas disponibles \\
{\bf C-x k} & Cierra la ventana actual \\
{\bf C-x 0} & Cierra la otra ventana 
\end{tabular}

\subsection{Algunas combinaciones de teclas}

A continuación, algunas otras combinaciones de teclas
que pueden resultar útiles en el uso de emacs.

\subsubsection{Deshacer y volver a hacer}

Para deshacer el último cambio realizado, se utiliza la combinación
{\bf C-\_}.  Esta combinación puede presionarse tantas veces como se desee
para ir deshaciendo todos los cambios realizados.

Si, llegado un punto, si quiere volver a realizar los cambios que se han
deshecho, simplemente se realiza cualquier cambio (por ejemplo, escribir un
caracter) y luego se vuelve a presionar {\bf C-\_} tantas veces como sea
necesario.

\subsubsection{Teclas de movimientos}

Dentro de emacs es posible utilizar los cursores para moverse a través del
texto del archivo, pero además es posible utilizar estas teclas. \\

\begin{tabular}{llc|cll}
{\bf C-n} & Baja una línea & & & {\bf C-p} & Sube una línea \\
{\bf C-f} & Avanza un caracter & & & {\bf C-b} & Retrocede un caracter \\
{\bf M-f} & Avanza una palabra & & & {\bf M-b} & Retrocede una palabra \\
{\bf C-a} & Principio de línea & & & {\bf C-e} & Fin de línea \\
{\bf M-a} & Principio de oración & & & {\bf M-e} & Fin de oración \\
{\bf M-arriba} & Principio de párrafo & & & {\bf M-abajo} & Fin de párrafo \\
{\bf C-v} & Sube una pantalla & & & {\bf M-v} & Baja una pantalla \\
{\bf M-$<$} & Principio de la ventana & & & {\bf M-$>$} & Fin de la ventana
\end{tabular}

\subsubsection{Teclas para copiar y pegar}

En emacs, para poder copiar y pegar, primero se inicia la selección del
texto, luego se mueve el cursor hasta el final de la selección (el programa
normalmente no indica que se está marcando el texto), y una vez que se
llega al final de la selección se presiona la combinación correspondiente a
cortar o copiar, según se desee.

\begin{tabular}{ll}
{\bf C-espacio} & Comenzar a marcar \\
{\bf C-w} & Cortar la región marcada \\
{\bf M-w} & Copiar la región marcada \\
{\bf C-y} & Pegar la región que se haya cortado o copiado.
\end{tabular}

\subsubsection{Teclas para realizar búsquedas}

\begin{tabular}{ll}
{\bf C-s} & Busca hacia abajo \\
{\bf C-r} & Busca hacia arriba \\
{\bf C-s C-s} & Repite la búsqueda \\
{\bf M-C-s} & Busca utilizando una {\it expresión regular} \\
{\bf M-\%} & Reemplaza en el texto, con confirmación
\end{tabular}

\subsubsection{Teclas de borrado}

\begin{tabular}{ll}
{\bf C-d} &  Borra un caracter \\
{\bf M-d} &  Borra una palabra \\
{\bf M-del} & Borra la palabra anterior \\
{\bf C-k}  & Borra una línea \\
{\bf M-k} & Borra una oración 
\end{tabular}

\newpage

\section{Scripts de Shell - Básicos}

Siempre que interactuamos con el shell estamos creando pequeños programas.
Cuando a estos pequeños programas los guardamos en un archivo que pueda
ejecutarse luego, lo llamamos un ``script''.  Estos scripts sirven, entre otras
cosas,  para tareas de automatización.

Los scripts de shell son básicamente programas escritos en el lenguaje del
shell, se parecen a los archivos .BAT del DOS.  Aunque es cierto que, si se van
a escribir más de varias decenas de líneas de script, es mejor recurrir a un
lenguaje diferente del shell, pensar en que los scripts de shell son solamente
pequeños programas sería cometer una injusticia con la flexibilidad y
comodidad que ofrecen al usuario.

Normalmente los scripts de shell se crean cuando es necesario combinar en una
única acción una tarea rutinaria.

Estos scripts pueden ser muy breves (una sola línea),
o bastante largos (varias pantallas).
Vamos a empezar con algunos ejemplos muy sencillos. 

\subsection{Primer Script de Shell}

Creamos un archivo que contenga: \verb!who | wc -l!, esto lo podemos hacer
utilizando el comando \verb!echo!, con la salida estándar a un archivo, o bien
utilizando el editor vi.  El archivo lo llamaremos \verb!cuantos!.

Para poder ejecutar este pequeño script, tenemos que utilizar el
intérprete del shell.  Hay dos formas de hacerlo: \verb!sh cuantos!,
invocará al sh para que interprete nuestro script y lo ejecute.

El archivo no lo podemos ejecutar directamente, porque al crearlo, lo hemos
creado como archivo de texto, y no tiene permisos de ejecución.  Para que
podamos ejecutarlo tenemos que agregarle el permiso: \verb!chmod u+x cuantos!.
Una vez que le hemos agregado el permiso, nuestro archivo ha pasado a ser un
ejecutable, y se lo puede invocar como a cualquier comando.  La línea para
invocarlo será: \verb!./cuantos!.

\subsection{La variable PATH}

Llama la atención el {\bf ./} que tenemos que agregar al principio 
para poder ejecutar el archivo.  Esto simboliza al directorio actual.  
Lo que estamos haciendo es diciéndole al shell que busque el archivo 
``cuantos'' en el directorio actual.  
Esto se debe a que el directorio actual no está en la
lista de los directorios en los que el shell busca para encontrar un determinado
comando.

Los directorios en los que el shell busca son {\bf /bin}, {\bf /usr/bin} y
algunos otros.  Están definidos en una variable llamada PATH.

Para poder ver el contenido de la variable PATH, podemos ejecutar
desde línea de comandos: \verb!echo $PATH!.
Es importante recalcar que la variable se llama {\bf PATH}, pero para
ver su contenido le agregamos el símbolo \$ adelante, este símbolo es un
meta-caracter de shell, como los vistos anteriormente, y le dice al shell que lo
que viene a continuación es una variable.

\subsection{Variables de entorno}

Así como PATH también existen muchas otras variables.  Algunas determinadas
por el sistema, y otras determinadas por nosotros.  

Llamamos {\it entorno} al conjunto de variables, como 
el PATH, el nombre de usuario,
el directorio actual, el directorio principal, las preferencias de lenguaje,
etc. que determinan a la consola que estamos utilizando en este momento.
Podemos ver cuales son las variables de nuestro entorno escribiendo:
\verb!set!.

A estas variables de entorno, nosotros podemos agregar nuevas variables.   Para
ello podemos escribir: \verb!variable=valor!.  Y haciendo 
\verb!echo $variable! podremos ver el valor que le asignamos a la variable.

Al ejecutar un programa, este programa recibe una copia de nuestro entorno,
donde algunas variables pueden mantenerse (variables exportadas), y otras 
pueden no estar.  Un programa puede modificar las variables que tiene en su
entorno, pero no las del entorno anterior.
A su vez, dentro de ese programa podemos ejecutar un nuevo programa, que
tendrá su propio entorno, con sus propias variables.

Para hacer que los programas hereden las variables que nosotros definamos,
existe un comando llamado \verb!export!, que nos asegura que los programas que
se ejecuten, reciban esa variable en su entorno. \\

{\bf Ejemplos}
\begin{itemize}

\item Escriba en la consola \verb!dia=sabado!, cree un script que contenga:
  \verb!echo Hoy es $dia!. Ejecute el script, a coninuación ejecute
  \verb!export dia! y vuelva a ejecutar el script. Explique lo sucedido.

\item Crear otro script, que contenga: \verb!variable2=valor2;export variable2; echo $variable2!.
  Ejecutar el script, y luego, desde la línea de comandos \verb!echo $variable2!.
  Esto no nos mostrará nada, ya que como dijimos antes, no se puede modificar
  el entorno anterior.

\item Crear otro script, que contenga: 
  \verb!cd /; pwd; echo $PWD; export PWD!.  Al ejecutar el script, notar que
  por más que tanto el \verb!pwd! como el \verb!echo! nos haya mostrado que el
  \verb!cd! había logrado cambiar de directorio, al volver del script,
  permanecemos en el directorio en el que estábamos al ejecutar el script.

\end{itemize}

\subsection{Parámetros de los comandos}

Cuando ejecutamos un comando, puede suceder que necesite parámetros.  En el
caso de los scripts, los parámetros se encuentran en variables especiales que
identificamos como \$1, \$2, \$3, etc.  El nombre de la variable nos indica la
ubicación del parámetro.

Para ver esto en un script muy sencillo, armaremos un script que contenga la
línea \verb!echo $1!, de forma que -al invocarlo- nos mostrará el
parámetro que le pasemos al ejecutarlo. \\

Para tener el caso de un script un poco más útil,
vamos a hacer un script que nos permitirá convertir rápidamente
en ejecutables a los próximos scripts que realicemos: \verb!chmod +x $1!. Le
pondremos de nombre {\bf cx}.
Para hacer ejecutable este script, vamos a aprovechar lo que ya escribimos y
haremos: \verb!sh cx cx!.

Podemos mejorar este script, de tal manera que reciba más parámetros y
pueda hacer ejecutables más archivos a la vez.  Podríamos escribir, por
ejemplo. \verb!chmod +x $1 $2 $3 ...!, pero existe una manera más
elegante (y más eficiente): \verb!chmod +x $*!. Al encontrar el \$*, el
shell lo reemplazará por todos los parámetros que haya recibido el script.
\\

Por último, veremos la utilidad de las comillas dobles (\verb!"!), en su
relación con los parámetros.  Usaremos un script que contenga la línea:
\verb!echo "Buen día $1"!.  Al ejecutarlo con un parámetro (por ejemplo,
Pedro), la salida del comando será \verb!Buen día Pedro!.

Si en el ejemplo anterior hubiéramos utilizado comillas simples, la salida
del comando hubiera sido \verb!Buen día $1!, ya que dentro de las comillas
simples el meta-caracter \verb!$! no es interpretado, mientras que dentro de
las comillas dobles si.

\section{Filtros - Básicos}

Existen una gran variedad de programas que reciben una entrada, la procesan y
emiten una salida, a este tipo de programas le llamamos filtros. Estos son una
parte fundamental del sistema ya que relacionando filtros simples se puede
conseguir prácticamente cualquier cosa, a nivel de administración de
archivos y scripts..

Entre estos filtros están: \\

\begin{tabular}{ll}
cat & para mostrar la entrada. \\
grep, tail, head y cut & para seleccionar una parte de la entrada. \\
less y more & para paginar la entrada. \\
sort &  para ordenar la entrada\\
tr & para alterar la entrada en forma ordenada. \\
comm y diff & para comparar dos entradas. \\
wc & para contar la entrada.
\end{tabular}

\subsection{grep}

Un comando muy útil que nos proporciona UNIX es \verb!grep!.  Su función
principal es imprimir por pantalla solamente las líneas que concuerden con un
patrón que nosotros le indicamos.

Por ejemplo: \verb!ls -l | grep archivo!, nos mostrará todas 
las líneas  del \verb!ls -l! que concuerden con \verb!archivo!. 

Algunas opciones de grep son: 
\begin{itemize}
\item \verb! -i! (ignore case) que no tiene en cuenta mayúsculas y minúsculas. 
\item \verb! -n! para que muestre el número de línea dentro del archivo.
\item \verb! -v! para que muestre las líneas que no concuerdan con la
palabra ingresada.
\end{itemize}

Vamos a hacer un ejemplo de una agenda sencilla, utilizando el comando grep y
unos scripts de shell.  En primer lugar necesitamos tener un archivo con unas
cuantas líneas de la forma: ``nombre: teléfono''.  Por lo menos cuatro o cinco
líneas, como para probar este ejemplo.

Una vez que hemos creado el archivo, crearemos el script, que se llamará 110,
y deberá contener la siguiente línea: \verb!grep -i "$*" agenda!.  Y para
buscar un teléfono dentro de nuestra agenda haremos: \verb!110 nombre!.

\subsection{tail}

El comando \verb!tail! nos permite ver la cola de un archivo, es decir sus 
últimas líneas (últimas 10 por omisión). Esto, aunque a simple vista no
parezca útil, resulta de gran utilidad para ver archivos grandes como, por
ejemplo, logs (archivos donde se guardan mensajes de estado y/o de errores).

Para probar el comando vamos a utilizar los logs del sistema, que se suelen
guardar en /var/log, en particular
/var/log/messages es el archivo que contiene gran parte de los mensajes del
sistema. Podemos hacer \verb!tail /var/log/messages! y compararlo con la salida
de \verb!cat /var/log/messages!.

Además a \verb!tail! podemos indicarle cuántas líneas queremos que nos 
muestre. Con la opción -20, por ejemplo, le diríamos que nos 
muestre 20 líneas y así con cualquier número que le pasemos. 
También podemos decirle que nos muestre el contenido del archivo a partir de 
una determinada línea, por ejemplo \verb!tail +5 archivo! nos mostrará 
el contenido del archivo desde la línea 5 en adelante. \\

Otro comando similar a \verb!tail! es \verb!head!.  Su comportamiento es muy
similar, pero en lugar de mostrar las últimas líneas de la entrada, muestra
las primeras.

\subsection{sort}

Este comando nos permite obtener una salida ordenada, si hacemos 
\verb! ls | sort! obtendremos la salida de ls con un orden alfabético.

Ahora probemos \verb!ls -i | sort!, \verb!sort! ordena la salida de \verb!ls!
alfabéticamente, eso quiere decir que los números no van a estar ordenados
de menor a mayor sino en orden alfabético. Para ordenarlos numéricamente
existe la opción -n, \verb!ls -i | sort -n!  producirá una salida ordenada
de menor a mayor.  Si quisiéramos, en cambio, que lo ordene de mayor a
menor, debemos usar \verb!ls -i | sort -nr!, es decir -r ordena en orden
inverso. \\

También podemos ordenar por una determinada columna, para entender esto de
una manera más clara veamos la salida de \verb!ls -l!, estas líneas pueden
ser ordenadas por tamaño, por nombre, por fecha, etc.  Para eso tenemos que
indicarle cuál columna tiene que ordenar y con qué criterio. 
Notar que sort cuenta las columnas empezando de 0.

Por ejemplo:

\verb!ls -l | sort +4nr! ordena la salida de \verb!ls! por el 
tamaño dejando los más chicos al final. En este caso, la n, que indica
ordenamiento numérico es opcional, ya que \verb!sort! decide
automáticamente el ordenamiento.

\verb!ls -l | sort +4n +8! ordena la salida de \verb!ls! primero 
por tamaño y luego por el nombre del archivo. En este caso, es necesario
poner la n, que indica ordenamiento numérico. \\

También existe un opción -u que nos permite eliminar las lineas iguales
adyacentes de la salida de sort.  Es decir que si nuestra salida produce dos
líneas iguales una debajo de otra, veríamos solamente una línea.

\subsection{tr}

Este comando nos permite transliterar caracteres, es decir cambiar determinado
caracter por otro. Si escribimos \verb!tr 'a-z' 'A-Z' < archivo!, 
veremos que tr transforma todas las minúsculas en mayúsculas.  

Los parámetros del ejemplo anterior son rangos (de la 'a' a la 'z' y de la
'A' a la 'Z'), pero no es necesario que lo sean. 
Lo que sí nos exige \verb!tr! es que los parámetros tengan
la misma cantidad de caracteres, o bien que el segundo sea un solo caracter. 
En este último caso reemplazará
todos los caracteres del primer parámetro con el del segundo.

La opción \verb!-c! indica que deben transliterarse todos los caracteres 
que no estén incluidos en el primer parámetro. \\

Ejemplo difícil:

\verb!cat archivo | tr -c 'a-zA-Z' '\n' | tr 'A-Z' 'a-z' | sort -u! 

El primer \verb!tr! convierte todo lo que no sea letras en \verb!\n! (retorno
de carro), el segundo convierte todas las mayúsculas en minúsculas y el
\verb!sort! del final las ordena alfabéticamente eliminando las líneas
iguales, con lo que obtenemos una palabra por línea.

\subsection{comm}

Este comando nos sirve para comparar el contenido de dos archivos, línea por
línea.  Para poder probar este comando, debemos crear dos archivos parecidos,
que tengan unas cuantas líneas en común, y otras distintas.  Luego, debemos
hacer: \verb!comm archivo1 archivo2!

La salida está separada en tres columnas: en la primera columna 
estarán las líneas que están en el primer archivo y no en el segundo, 
en la segunda columna veremos las líneas del segundo archivo 
que no estén en el primero y
por último, en la tercera columna, las que están en los dos.

Además podemos indicar cuál de esas columnas no queremos que muestre, por
ejemplo, utilizando: \verb!comm -12 arch1 arch2! muestra solamente la tercera columna, 
es decir, las líneas que están en ambos archivos. 

El problema que tiene \verb!comm! es que espera que las líneas estén
ordenadas alfabéticamente, o en la misma posición dentro del archivo.  De
modo que puede suceder que archivos muy similares sean procesados por
\verb!comm! como archivos muy diferentes.  Para procesamiento más avanzado
de diferencias de archivos puede utilizarse el comando \verb!diff!. \\

Ejemplo:

En {\bf /usr/share/dict/} normalmente tenemos un archivo diccionario, en el
cual encontramos una palabra por renglón. En especial, el archivo {\bf
words} suele ser un symlink al diccionario del idioma de nuestro sistema. 

Lo que vamos a hacer es armar un pequeño analizador ortográfico, 
usando los filtros recién vistos.
Utilizaremos \verb!comm! para verificar si la palabra está en el
diccionario, y que nos avise si no está. 
Primero deberemos llevar el texto a una palabra por línea ordenada 
alfabéticamente (que es el ejemplo que utilizamos con \verb!tr!). 
Y luego, utilizar \verb!comm! para comparar con el diccionario. \\

El comando completo será: 
\begin{verbatim}
cat archivo | tr -c 'a-zA-Z' '\n' | tr 'A-Z' 'a-z' | sort -u |
comm -23 - /usr/share/dict/words
\end{verbatim}

Notar que el - como parámetro del \verb!comm! le indica que use la entrada
estándar para leer el primer archivo.

\section{Filtros - Avanzados}

Existen, además de los filtros que ya vimos, otros dos filtros muy
poderosos, llamados \verb!sed! y \verb!awk!. Tienen una sintaxis tan avanzada
que se los considera pequeños lenguajes de programación. En este curso no
los vamos a estudiar. 

Sin embargo, gran parte de la potencia de estos es su manejo de expresiones 
regulares que es el mismo que el de \verb!grep!, que veremos a continuación.

\subsection{grep}

Como ya vimos, podemos hacer \verb!grep patrón archivos! y veremos las
líneas que concuerdan con el patrón en esos archivos,

La gran fortaleza de \verb!grep! se encuentra en la sintaxis
del patrón. Hasta ahora, el patrón que ingresábamos era simplemente una
palabra, y eso le indicaba a \verb!grep! que debía encontrar las líneas que
contuvieran esa palabra.

Sin embargo, en ese patrón podemos incluir lo que se llama una {\it expresión
regular}.  Las expresiones regulares son cadenas de caracteres que permiten
transmitirle a los filtros una búsqueda mucho más avanzada.  Tenemos la
posibilidad, por ejemplo, de indicar si queremos que algo esté al principio o
al final de un archivo, si queremos que esté repetido una determinada cantidad
de veces, etc. 

\begin{itemize}

\item El símbolo \verb!^!  indica comienzo de línea, es decir que el patrón que
esté a continuación debe estar al principio de la línea.

Por ejemplo, podemos querer ver todas las líneas del comando \verb!who! que
comienzan con un nombre de usuario en particular.  Esto lo haríamos
ejecutando: \verb!who | grep ^usuario!. 

\item De una manera similar \$ al final de un patrón significa que debe estar
  ubicado al final de la línea.

\item El . actúa como el ? en el shell, concuerda con cualquier caracter, una
  sola vez.

Por ejemplo, si hacemos \verb!ls -l | grep '^.......rw'! veremos los archivos
que tengan permisos de lectura y escritura para el resto mundo. 

\item También tenemos un manejo de rangos \verb![...]! muy parecido al del
  shell.

\item El * nos permite que el último caracter se encuentre 0 o más veces. Es
  decir, utilizando \verb!.*! obtendremos el mismo comportamiento que el del
  \verb!*! de shell.

  Por ejemplo, \verb!ls -l | grep '^.*rw'! puede mostrarnos los archivos que
  tengan algún permiso de escritura y lectura, o bien algún archivo que
  contenga las letras rw en su nombre.
\end{itemize}

Un problema común es que muchos de los caracteres que \verb!grep! usa como
caracteres especiales son los mismos que usa el shell como meta-caracteres y
esto puede llegar a confundirnos mucho, por lo que usamos los patrones entre
comillas simples ('...') para evitar problemas de interpretación del shell.
Pero también podemos querer que el grep no interprete determinado caracter en
ese caso usamos \verb!\ !.

\subsection{egrep o grep -E y fgrep o grep -F}

En realidad, grep es el primero de una familia de comandos, egrep tiene un set
de expresiones regulares más completo, mientras fgrep esta optimizado para
manejo de archivos grandes, pero solo busca literales. 

En la actualidad la versión GNU de estos comandos resume los tres dentro de grep
con las opciones -E y -F, pero existen más, como el ngrep (network grep),
grepmail, etc.

\subsection{Expresiones de grep, egrep}

Se listan a continuación las expresiones de grep y egrep, 
por orden de precedencia, con una explicación somera de su significado. \\

\begin{tabular}{c|p{12cm}}
Expresión & Significado \\
\hline
{\bf c} & cualquier caracter no especial, concuerda a si mismo \\
{\bf $\backslash$c} & cancela significado especial de c \\
{\bf \verb!^!} & inicio de línea \\
{\bf \$} & fin de línea \\
{\bf .} & cualquier caracter individual \\
{\bf \verb![...]!} & cualquiera de los caracteres en ...; 
incluye rangos de tipo a-z \\
{\bf \verb![^...]!} & cualquiera de los caracteres que no esté en ...; 
también se incluyen los rangos a-z \\
{\bf r*} & cero o más ocurrencias de r\\
{\bf r+} & una o más ocurrencias de r (egrep)\\
{\bf r?} & cero o una ocurrencia de r (egrep)\\
{\bf \verb!r1|r2!} & expresión r1 o expresión r2 (egrep)\\
{\bf $\backslash$(r$\backslash$)} & agrupar expresión regular r (grep)\\
{\bf (r)} & agrupar expresión regular r (egrep)\\
{\bf $\backslash$num} & lo que concordó con la num-ésima expresión regular agrupada\\
\end{tabular}

Ante la pregunta posible, que puede surgir mirando esta tabla, de cuál es
el significado de \verb!(r)! cuando se utiliza grep, la respuesta es que
simplemente concuerda con los paréntesis, como cualquier caracter sin
significado especial

\subsection{Ejercicios}

Utilizando el diccionario que se encuentra en el directorio
{\bf /usr/share/dict}, encontrar las expresiones regulares que concuerdan
con los siguientes tipos de palabras.

\begin{enumerate}
\item Palíndromos de 3 letras (ej: ala, asa, ata).
\item Palíndromos de 4 letras (ej: erre).
\item Palíndromos desde 3 a 9 letras (ej: salas, rallar, anilina)
\item Palabras que tienen todas sus letras ordenadas alfabéticamente.
\item Palabras que tienen todas sus vocales ordenadas alfabéticamente.
\item Palabras que tienen todas las vocales. (ayuda: utilizar varios
\verb!grep! encadenados).
% Respuesta:
%grep '^[^aá]*[aá][^a]*$' /usr/share/dict/spanish | grep '^[^eé]*[eé][^eé]*$' | grep '^[^ií]*[ií][^ií]*$' | grep '^[^oó]*[oó][^oó]*$' | grep '^[^uú]*[uú][^uú]*$'
\end{enumerate}

\section{Más scripts de Shell}

Además de las herramientas para manejo de variables que se explicaron
anteriormente, el shell nos permite utilizar herramientas para manejo de ciclos
y para estructuras condicionales, veremos a continuación cómo utilizar y
manipular los parámetros y luego ejemplos que utilizan {\bf if}, 
{\bf for}, {\bf while} y {\bf case}, junto con varias herramientas y
características del shell, como manejo de funciones, valores de retorno, etc.

\subsection{Parámetros}

Como ya hemos visto, los scripts de shell pueden recibir y manipular
parámetros.  Estos parámetros se representan dentro de los scripts como \$1, 
\$2, etc.  El conjunto de todos los parámetros está representado por \$*,
mientras que la cantidad de parámetros está representada por \$\#.

Existe, además un comando llamado {\bf shift} que permite eliminar el primer
parámetro de la lista, y correr todos los parámetros.  De tal manera que el
segundo parámetro pasa a ser \$1 y así. 

Veremos un ejemplo sencillo:

\begin{verbatim}
echo "Cantidad de parámetros: $#"
echo "Primer parámetro: $1"
shift
echo "Segundo parámetro $1"
shift
echo "El resto de los parámetros $*"
\end{verbatim}

El comando {\bf set} nos permite ver todas las variables de entorno.  Pero
además, nos permite asignarle valor a los parámetros \$1, \$2, etc.  Por
ejemplo:

\begin{verbatim}
set Viva GNU Linux
echo "Primer parámetro: $1"
echo "Segundo parámetro: $2"
echo "Tercer parámetro: $3"
\end{verbatim}

\subsection{if}

Es la estructura que permite ejecutar los comandos solamente si se cumple
una determinada condición.  La sintaxis más usual:

\begin{tabular}{p{6cm}p{6cm}}
\begin{verbatim}
  if [ condición ]; then
    comandos
  else
    comandos
  fi
\end{verbatim}
&
\begin{verbatim}
  if [ condición ]; then
    comandos
  fi
\end{verbatim}
\end{tabular}

En realidad, los corchetes \verb![  ]! son un comando en si mismo,
también llamado \verb!test!,
por eso, para armar la condición utilizamos la sintaxis de test.
(para más información: \verb!man test!). \\

Las condiciones serán de este estilo: \\

\begin{tabular}{ll}
!condición & Si condición es falsa \\
condición1 -a condición2 & Las dos condiciones son verdaderas \\
condición1 -o condición2 & Una de las dos condiciones es verdadera \\
cadena-de-caracteres & La cadena no esta vacía \\
-z cadena-de-caracteres & La cadena esta vacía \\
cadena = cadena & Las dos cadenas son iguales \\
cadena != cadena & Las cadenas son distintas \\
entero -eq entero & Los enteros son iguales \\
\end{tabular}
\\

Por otro lado, también podemos colocar otra cosa que no sea el comando test,
otros programas, que le devuelvan al if un cero o un uno, 
que el if luego interpretará como {\it false} o {\it true} respectivamente. 
O también, la palabras {\bf true} y {\bf false}.

Realizaremos un script que escriba un mensaje si hay más de un
usuario conectado y otro diferente si hay sólo un usuario conectado.

\begin{verbatim}
cuantos=`who | wc -l`

if [ $cuantos -gt 1 ]; then 
        echo "Hay $cuantos usuarios conectados"
else
        echo "Estás solo en el mundo"
fi
\end{verbatim}

En este script, primero guardamos la cantidad de usuarios conectados al sistema
en la variable {\bf cuantos}. Esto lo hacemos utilizando las comillas
invertidas, que son un recurso que nos provee el shell para utilizar la salida
de los comandos en nuestro código; cada bloque encerrado por las comillas
invertidas es reemplazado por la salida del comando en cuestión. Otra forma de
hacer esto es utilizando una sintaxis alternativa a las comillas invertidas
\verb!$(...)!, esta forma tiene la ventaja que podemos anidarla fácilmente.

Luego utilizamos la estructura de {\bf if} para compararlo con 1, la
opción -gt del comando {\bf test} significa mayor que. \\

{\bf Recordar}: el comando [ normalmente es sinónimo del comando test.

\subsection{for}

Es una estructura que permite una iteración durante un número 
determinado de veces.

La sintaxis:

\begin{verbatim}
  for variable in lista; do
    comandos
  done
\end{verbatim}

La variable, cuando se la coloca al lado del for, no lleva el signo \$ 
adelante, pero si en los comandos se hace referencia a ella, se debe 
escribir \$variable.

La {\it lista} puede ser:       

Una lista de números. Ej: 1 2 3 4

Una lista de archivos. Ej: *.java

Una lista de argumentos. Ej: \$* \\

Por ejemplo, si quisieramos hacer copias de varios archivos agregandoles una
extensión, podriamos hacer.

\begin{verbatim}
for archivo in *; do
        cp "$archivo" "$archivo.bak"
done
\end{verbatim}

A continuación realizaremos un script que recibe por parámetro todos los
usuarios que queremos saludar y les manda un saludo a cada uno solamente si 
están conectados al sistema.

\begin{verbatim}
for i in $*; do
        if who | grep "^$i" > /dev/null; then
                write $i << EoT
Hola $i!
EoT
        fi
done
\end{verbatim}

Esta vez utilizamos la estructura {\bf for} para procesar los argumentos de 
nuestro comando. Para cada uno de los parámetros recibidos, verificamos si ese
usuario está conectado o no.  Para esto, abusamos un poco del if y 
demostramos que no es obligatorio usar test con el if. Aquí utilizamos la
salida de un comando.

Si el usuario está conectado usamos el comando {\bf write} (que le manda un 
mensaje a la consola del usuario), para enviar un saludo a cada uno.

Para poder mandar el mensaje, utilizamos un meta-caracter de shell muy especial.
Este meta-caracter comienza con {\verb!<< EoT!}, y con esto le indica al shell
que la entrada de este comando es todo lo que ingresemos a continuación hasta la
que encuentre una línea que solamente contenga la cadena {\verb!EoT!}.  

Esta cadena podría ser cualquier otra, podríamos por ejemplo poner 
{\verb!<< blablabla!}, y luego deberíamos terminar el texto con una línea que
contenga {\verb!blablabla!}.

\subsection{while} 

Es una estructura que permite una iteración hasta que una determinada 
condición no se cumpla.

La sintaxis:
\begin{verbatim}
  while [  condición ]; do
    comandos
  done
\end{verbatim}

La condición es equivalente a la del if.

A continuación veremos otra manera de procesar los parámetros recibidos. 

\begin{verbatim}
while [ "$*" ]; do
        echo $*
        shift
done
\end{verbatim}

Este simple script imprime en cada línea cada uno de los parámetros
recibidos. Vemos que si omitimos las \verb!" "! el comando test nos devuelve un error,
pues espera un solo parámetro. 

\subsection{case}

En casi todos los lenguajes de programación encontramos una estructura que nos
permite realizar distintas acciones según el valor de una determinada variable.

En el caso del shell esta estructura es {\bf case}.  Y se utiliza con la
siguiente sintaxis:

\begin{small}
\begin{verbatim}
        case $variable in
                     patron1)
                              comandos
                              ;;
                     patron2)
                              comandos
                              ;;
        esac
\end{verbatim}
\end{small}

El patrón con el que comprobamos al utilizar {\bf case} es similar al que
utiliza el shell (* para cualquier cadena, ? para cualquier caracter, [ ] para
rangos, $\backslash$ para escapar valores especiales y ' ' para escapar cadenas
completas), además de un muy cómodo {\verb!|!} para usarlo como o. \\

Para ver cómo es su funcionamiento, estudiaremos un ejemplo, en el que
utilizamos el comando {\bf cal}.  Este comando nos permite visualizar
calendarios.  Utilizado sin ninguna opción nos muestra el mes actual.
Al agregar un número a continuación (por ejemplo {\bf cal 2020}) nos muestra
el calendario de ese año. Y si le pasamos dos parámetros (por ejemplo {\bf cal
11 2002}) nos muestra el calendario de ese mes y ese año.

Este comando no entiende nombres de meses (enero, febrero, etc), y al ejecutar
{\bf cal 10} la salida será el calendario del año 10, no del mes 10 del año
actual, que es más probablemente nuestra expectativa.
El script que realizaremos permitirá obtener un nuevo comando (ncal) que tenga
estas funcionalidades.

\begin{small}
\begin{verbatim}
# Analizamos los parámetros.
case $# in
   0) set `date`    # Si no vino ningún parámetro,
      m=$2          # mostramos el calendario del mes actual
      y=$6          # y del año actual.
   ;;
   1) m=$1          # Si vino un sólo parámetro,
      set `date`    # mostramos el calendario de ese mes
      y=$6          # y del año actual.
   ;;
   2) m=$1          # Si vinieron dos parámetros,
      y=$2          # mostramos el calendario de ese mes y año.
   ;;
esac

# Seleccionamos el mes que corresponde.
case $m in
   jan*|Jan*|ene*|Ene*) m=1 ;;
   feb*|Feb*)           m=2 ;;
   mar*|Mar*)           m=3 ;;
   apr*|Apr*|abr*|Abr*) m=4 ;;
   may*|May*)           m=5 ;;
   jun*|Jun*)           m=6 ;;
   jul*|Jul*)           m=7 ;;
   aug*|Aug*|ago*|Ago*) m=8 ;;
   sep*|Sep*)           m=9 ;;
   oct*|Oct*)           m=10 ;;
   nov*|Nov*)           m=11 ;;
   dec*|Dec*|dic*|Dic*) m=12 ;;
   [1-9]|10|11|12)      ;;          # El mes era numérico.
   *)                   y=$m; m=""; # Sólo vino el año.
esac

# Llamamos al calendario con el mes que elegimos.
cal $m $y
\end{verbatim}
\end{small}

Un uso muy frecuente del case de shell se encuentra en los {\it demonios}
de GNU/Linux.  Los demonios son los servicios que se ejecutan en el sistema
más allá de qué usuario es el que está loggeado.  Suelen existir scripts de
shell que se encargan de iniciarlos, detenerlos, reinciarlos, etc. 

\subsection{Funciones}

El shell nos provee de un manejo de funciones. Una función es un conjunto de
instrucciones encerradas en un bloque de código, una caja negra que hace
determinado trabajo.
Deben ser declaradas antes de poder llamarlas, y para llamarlas
alcanza con tipear su nombre.

\begin{small}
\begin{verbatim}
# declaración de función
función () {
        comandos
}
# declaracion alternativa.
function funcion {
        comandos
}

función # Llamado a función
\end{verbatim}
\end{small}

Las funciones reciben sus parámetros en \$1, \$2, \$*, etc. Y devuelven
valores entre 0 y 255, esto se consigue con la instrucción de
shell {\bf return}.  El valor que devuelven puede ser accedido en el script
en la variable \$?.
Normalmente, las funciones acceden a variables globales, para poder usar locales
se debe usar la instrucción de shell {\bf local}.

A continuación, algunos ejemplos que se proponen armar una calculadora en
shell.

\begin{small}
\begin{verbatim}
res=0; rem=0
add () {
        local i
        case $# in
        0)      res=0 ;;
        *)      res=$1
                shift
                for i in $*; do
                        let res+=$i
                done
                ;;
        esac
}
\end{verbatim}
\end{small}

Se trata de una función que suma todos los parámetros que recibe.  Si no
recibe ningún parámetro el resultado es cero.
En cambio, si recibe algún parámetro, inicializa la variable {\it
res} con el valor del primer parámetro, que luego borra de la lista de
parámetros con el comando {\bf shift}.  Y a continuación suma uno a uno,
todos los otros parámetros, utilizando el comando de shell {\bf let}, que
permite realizar operaciones aritméticas simples.

Así como la suma, podemos ver también la multiplicación y la
división.

\begin{small}
\begin{verbatim}
mul () {
        local i
        case $# in
        0)
                res=0
                ;;
        *)
                res=$1
                shift
                for i in $*; do
                        let res*=$i
                done
                ;;
        esac
}
div () {
        local i
        case $# in
        2)
                case $2 in
                0)
                        echo "Error: división por cero";
                        res=0; rem=0
                        return 1
                ;;
                *)
                        let res=$1/$2
                        let rem=$1%$2
                ;;
                esac
        ;;
        *)
                res=0; rem=0
        ;;
        esac
}

add 3 255 123 123 30 29 4
mul $res 2 2
div $res 0
echo $res; echo $rem
\end{verbatim}
\end{small}

Existen aún más capacidades para los scripts de shell, que no se explican
en este curso.  Más información puede encontrarse en la gran documentación
disponible en Internet, o leyendo el manual de bash.


\end{document}
