Sep 192007
 

Algunos conceptos importantes sobre directorios y ficheros en Linux.

Aunque no sean cosas específicas de bash, ni de la shell, y como el curso es para principiantes se hace imprescindible ir comentando ciertos aspectos del sistema operativo, así como los comandos y utilidades más usuales, y que todo usuario que maneje la shell debe conocer. Porque ambas cosas van ligadas, shell y sistema operativo. Como estamos empezando el curso empiezo por lo más básico, así que a los que ya tengáis bastante soltura con el sistema, puede que estos conceptos ya os suenen algo, o mucho, o que incluso los tengáis dominadísimos, pero bueno, yo creo que un repasito nunca viene mal.

Bajo la mayoría de sistemas operativos (incluyendo por supuesto a linux), existe el concepto de fichero. Un fichero es simplemente un conjunto de información con un nombre. Cualquier documento que guardamos dándole un nombre es un fichero. La foto que le hice el otro día a mi sobrino y que le he llamado ‘Damián.jpg’ es un fichero. El curriculum que escribí para ver si me admitían en la empresa Benito y compañía, y al que llamé ‘Curriculum para Benito Y Cia.odt’ también. El vídeo ese que edité de la cámara de video y que grabé como ‘Cumpleaños de Ada.mpg’ también es un fichero.

Para mayor comodidad los ficheros se organizan en directorios. Un directorio no es más que una colección de ficheros. Puede entenderse (y de hecho así se simboliza en la mayoría de entornos gráficos) como una ”carpeta” que puede contener muchos ficheros diferentes. Los directorios también tienen nombres, con los que se les identifica. Además, los directorios se mantienen en una estructura de tipo árbol; es decir, los directorios pueden contener otros directorios.

Por tanto decimos que un fichero tendrá siempre un nombre y estará contenido en un directorio. Y puede haber otro fichero distinto que tenga el mismo nombre en otro directorio, pero nunca en el mismo.

Podemos referirnos a un fichero o a un directorio por su ‘nombre de ruta’, esto es un nombre que nos indica cual es el nombre del elemento (fichero o directorio), y que esté precedido por el nombre de ruta del directorio que lo contiene, para separar los nombres de los distintos elementos que componen un nombre de ruta se utiliza un caracter separador. Como seguramente ya sabrás, los nombres de ruta en Linux, utilizan el caracter ‘/’ como separador, igual que en las URL de internet, en lugar del ‘\’ que usa Windows o DOS. El nombre de ruta de un elemento (ya sea de un fichero o de un directorio) lo identifica de manera unívoca entre todos los demás elementos del sistema informático. No puede haber dos elementos con el mismo nombre de ruta.

Para verlo como un ejemplo la foto de mi sobrino, a la que llamé ‘Damián.jpg’ la había guardado en un directorio que se llamaba fotos, y que estaba dentro de mi directorio personal que se llama redy, que a su vez está en el directorio donde el sistema guarda normalmente los directorios personales de todos los usuarios, y que se llama home. Por lo tanto el nombre de ruta de la foto será ‘/home/redy/fotos/Damián.jpg’

Es importante decir que a diferencia de otros sistemas operativos en Linux los nombres de fichero y de directorio (como casi todo) son, como dirían los anglosajones ‘case sensitive‘, es decir que no es lo mismo /usr que /Usr que /USR, así que mucho ojo a como escribimos.

También hay que decir que en muchos sistemas operativos existe un concepto que son las unidades, cada disco, o partición de un disco, cada medio de almacenamiento (diskette, cd, dvd, pendrive, tarjeta de memoria sólida… ) tiene un nombre de unidad y dentro de esa unidad hay un árbol de ficheros y directorios. En linux y la mayoría de los unix ese concepto no existe, todos los árboles de todas las unidades están formando ramas de un único arbol cuyo comienzo está en lo que llamamos directorio raíz, que no tiene nombre y tiene como nombre de ruta un único caracter ‘/’ sin nada más.

En cualquier sesión de la shell existe un concepto que es el directorio de trabajo. Podemos consultar y cambiar el directorio de trabajo a nuestro antojo, si mencionamos el nombre de un fichero sin especificar su nombre de ruta se entiende que nos referimos al fichero de ese nombre que se encuentra en el directorio de trabajo.

Para consultar cual es el directorio de trabajo usaremos el comando pwd (print working directory)
$ pwd
/home/redy

Para cambiarlo podemos usar el comando cd (change directory) seguido del nombre de ruta del directorio al que queremos cambiar. Nuestro directorio de trabajo por defecto al iniciar una sesión de shell será nuestro directorio personal generalmente ‘/home/nombre_de_usuario’. Como ese es un nombre de ruta muy usado tiene una abreviatura. Es lo mismo escribir la olilla ‘~’ que poner la ruta de nuestro directorio personal. (La olilla ‘~’ en teclado español en la mayoría de los Linux se obtiene pulsando <Alt-Gr> y la tecla de abrir admiración ‘¡’, o también <Alt-Gr>Ñ ). Así que en mi caso será lo mismo escribir ‘cd /home/redy’ que escribir ‘cd ~’. Y concretamente en el comando cd hay todavía una forma más sencilla de ir a nuestro directorio personal que es escribir el comando cd sin ningun argumento.

cd /etc
pwd
/etc
cd
pwd
/home/redy

Claro que si queremos hacer algo temporalmente en otro directorio para luego volver al que estábamos, igual nos es más útil usar pushd y popd. El comando pushd hace lo mismo que cd pero ‘recuerda’ dónde estaba antes de cambiarse, de tal manera que luego solo tenemos que hacer un popd para volver al directorio de dónde partimos. pushd siempre requiere un argumento, el nombre del directorio al que queremos cambiar, popd no requiere argumentos, regresará siempre al directorio donde estábamos antes del último pushd que ejecutamos. Se pueden anidar todos los pushd que se quieran. Se puede consultar la lista dónde pushd va guardando los directorios con el comando dirs. Se trata de una lista de las que los informáticos conocemos como ‘pila’ o ‘lista LiFo’ (Last in First out: El último en entrar será el primero en salir). Estas listas se comportan como si fuese apilando cosas, de ahí el nombre de ‘pila’. Imagina una pila de platos: a medida que vas poniendo platos la pila va creciendo, y cuando quieres coger un plato coges el de arriba de todo que fue el último que pusiste. Pues esta lista es igual, los elementos se añaden por el principio de la lista de tal manera que cada vez que haces un pushd el directorio de trabajo antiguo se añade al principio de la lista y los demás elementos que ya tenía quedan a continuación. Cuando se hace un popd se quita el primer elemento de la lista (que en realidad es el último que se ha metido) y se restablece el directorio de trabajo a donde indica ese elemento.

$ pwd
/home/redy
$ pusd /usr/bin
$ pwd
/usr/bin
$ pushd /usr/share
$ pwd
/usr/share
$ dirs
/usr/share /usr/bin ~
$ popd
$ pwd
/usr/bin
$ popd
$ pwd
/home/redy

Nombres de ruta absolutos y relativos al directorio de trabajo

En linux (y UNIX) si un nombre de ruta comienza con la barra ‘/’, se entiende que nos referimos al elemento (ya sea un fichero o un directorio) que designa dicho nombre de ruta de forma absoluta; es decir es el camino entero a seguir desde el directorio raíz. Por el contrario, si no empieza con ‘/’ se entiende que lo hacemos de forma relativa al directorio de trabajo, en el que nos encontramos. Así ‘/usr/bin’ denomina siempre al directorio bin que hay dentro del directorio usr que a su vez cuelga del directorio raíz. Mientras que ‘bin’ puede designar al directorio /usr/bin si n nuestro directorio de trabajo es /usr o a /usr/local/bin si el directorio de trabajo fuese /usr/local. Si hablamos de ficheros es exactamente lo mismo, se puede uno referir a un fichero dando su nombre de ruta de forma absoluta o relativa al directorio de trabajo. Así fichero.txt se entiende que está en el directorio de trabajo, mientras que /tmp/fichero.txt designa siempre al fichero.txt que se encuentra en el directorio /tmp

existen dos nombres de elemento un poco especiales: el elemento ‘..’ se utiliza para
referirnos al directorio padre, y ‘.’ para referirnos al directorio actual.
Así si por ejemplo te encuentras en el directorio /home/redy ‘..’ será el
directorio /home y ‘.’ será el mismo directorio ‘/home/redy’. Si usamos estos elementos en nombres de rutas podemos recorrer hacia arriba nuestro arbol a nuestro antojo. Por ejemplo estando en el mismo /home/redy el nombre relativo ../ada/fotos será /home/ada/fotos. O suponiendo que nuestro directorio de trabajo en un momento dado es /usr/share/icons/hicolor
../../../bin será /usr/bin. No es práctico pero algo como fotos/../fotos/./../fotos/. es un nombre de ruta válido que recorre hacia arriba y hacia abajo nuestro árbol para dejarnos en el mismo sitio dónde estábamos.

Directorios usuales en linux:

  • / Es el directorio raíz, todo cuelga de él.
  • /bin En este y otros directorios llamados bin es donde normalmente se encuentran los programas ejecutables.
  • /sbin En este y otros directorios llamados sbin es donde normalmente se encuentran las utilidades para administrar el sistema.
  • /dev En este directorio se encuentran unos ficheros especiales que sirven para comunicarse con los diversos dispositivos de hardware que puede haber en nuestro PC.
  • /etc Aquí es donde se guardan los ficheros de configuración globales.
  • /home Es donde residen los directorios personales de cada usuario.
  • /lib Se guardan aquí las bibliotecas de enlazado dinámico, que contienen funciones y rutinas comunes y reutilizables, y que son usadas por muchos programas.
  • /mnt Es donde se suelen montar los diversos dispositivos de almacenamiento, como diskettes o CDROMS, u otros discos duros etc… en algunas distribuciones los dispositivos removibles se montan en /media en lugar de en /mnt
  • /opt En algunas distribuciones aquí se instalan componentes opcionales.
  • /tmp para guardar los archivos temporales.
  • /usr Contiene más o menos los mismos directorios que el raiz, hay un bin, un sbin, un lib etc… los ficheros que no son imprescindibles en el arranque están aquí, mientras que los imprescindibles cuelgan del raíz. Esto es así porque el sistema puede estar en una unidad de red, pero tiene que tener en un disco local al menos lo mínimo para arrancar, acceder a la red y montar el resto del sistema en /usr.
  • /var Aquí se almacenan varios ficheros, como las colas de impresión y de correo, los ficheros de log, etc…
  • /usr/local Reproduce de nuevo la estructura del raíz y de /usr, y al igual que estos también suele contener un bin, un lib, un etc… en /usr/local van normalmente los ficheros que compilamos a partir del código fuente en nuestra máquina, para distinguirlos de los que se instalan con la distribución, que ya vienen compilados.

Esto es un somero resumen, para informacón mas detallada podéis consultar: Estructura del Sistema de Archivos de Linux

Como obtener ayuda uno mismo

Como vamos a empezar a ver algunos comandos útiles, y yo no puedo explicar a fondo todas y cada una de sus opciones, y como sé que sois curiosos os voy a explicar como obtener mucho más información de lo que yo os voy contando en este curso.

–help

Generalmente cada comando tiene su ayuda y su pagina de manual. La mayoría de los comandos admiten el argumento –help que muestra una breve ayuda con la sintáxis de uso. Veamoslo por ejemplo con el comando chsh que usábamos en el capítulo pasado:

$ chsh --help
Uso: chsh [ -s shell ] [ --list-shells ] [ --help ] [ --version ]
[ nombredeusuario ]

Cuando nos ponen la sintaxis de un comando, se indican en paréntesis cuadrados los argumentos opcionales. En este caso todos los argumentos son opcionales quiere esto decir que podemos poner el comando chsh sin ningún argumento. Veamos otro ejemplo, el comando top no lo conocemos, se usa para ver quien consume más recursos del sistema, lo veremos más adelante pero vamos a pedirle ayuda a ver que nos dice:
$ top --help
       top: procps version 3.2.5
 usage: top -hv | -bcisS -d delay -n iterations [-u user | -U user] -p pid [,pid ...]

Aquí ya vemos cosas nuevas, veis que hay una barra vertical ‘|’ entre varias opciones. Las opciones ‘h’ y ‘v’ son de ‘help y de version’ el resto de opciones afectan a su conportamiento si le pedimos ayuda o queremos saber la versión, no queremos que se ejecute luego no procede ponerle las otras opciones. La barra vertical indica justo eso que o ponemos lo uno o lo otro, pero no ambas cosas. Dentro del paréntesis cuadrado volvemos a encontrarla [-u user | -U user] indicando que podemos usar o bine la -u minúscula o la -U mayúscula seguida siempre de un nombre de usuario pero no ambas. Al final en la opción ‘-p pid [,pid …]‘ (pid se refiere a proccess id, identificador de proceso), nos indica que después de una p hay que poner al menos un pid y opcionalmente una lista de ellos separados por comas.

Otras veces la ayuda es tan extensa que no cabe en pantalla, prueba por ejemplo

$ ls --help

Si te ocurre esto en una terminal de texto (recuerda <Control><Alt><F1-6>) puedes usar la tecla de mayúsculas combinada con las de retroceder y avanzar página para moverte hacia atrás y hacia adelante. En una terminal gráfica generalmente también funcionan esas teclas, pero además suele tener una barra de desplazamiento para hacerlo a golpe de ratón. Otra opción cuando sabemos de antemano que no va acaber es añadir al final del comando un |more

ls --help |more

Esto hace (ya veremos gracias a que mecanismo a su debido tiempo) que la salida salga paginada. Cada página pone al final el prompt ‘–Más–’ y hace una pausa. Si pulsamos la tecla de espacio avanzamos a la siguiente página, con intro avanzamos línea a línea, y si ya hemos encontrado lo que buscábamos y no queremos seguir leyendo hasta la última página pulsamos la ‘q’ de (quit). El único inconveniente de esto es que |more siempre pagina hacia adelante no podemos ir hacia atrás. Por eso inventaron otro filtro mucho más práctico que es |less, que funciona de manera parecida a |more pero con muchísimas más posibilidades básicamente podemos usar las flechas arriba y abajo o las teclas de inicio fin avance y retroceso de página e igualmente usaremos la ‘q’ para salir.

man

El comando man invoca al manual. Si ponemos man –help nos dirá que, entre otras muchas opciones que no voy a explicar, hay un parámetro obligatorio que es el nombre de un comando. Así que podemos poner cosas como:


man ls
man chsh
man man

Como los manuales de los comandos suelen ser largos siempre se paginan (sin necesidad de ponerlo en el comando) con |more o con |less, dependiendo de la configuración de tu sistema. Lo digo por si no encuentras como salir del manual, tienes que usar la ‘q’ (de quit), recuerdas…

¿Porque con algunos comandos no funciona ni man ni –help?

Bueno es complejo responder a esa pregunta. No todos los programadores le ponen un parámetro –help a sus programas. No todos adjuntan una página de manual junto con su programa. Por otra parte hay comandos que son internos del propio bash (como veremos más adelante), en este último caso la página man nos redirigirá a un breve resumen de los comandos internos de bash, y la forma correcta de obtener más ayuda es usando el comando ‘help’. Por ejemplo.

$ help pushd

Hay que hacer notar el hecho de que no todas las páginas man o las ayudas están traducidas, así que a veces obtendrás la ayuda en inglés, se están traduciendo cada vez más cosas, pero es un largo camino por recorrer.

Comandos básicos para trabajar con directorios y ficheros

  • mkdir nombre_de_directorio Crea un nuevo directorio.
  • rmdir nombre_de_directorio Borra un directorio, (debe estar vacío).
  • cd nombre_de_ruta_de_directorio Nos lleva al directorio que digamos, haciendo que sea el directorio de trabajo, si no especificas un nombre te lleva tu directorio personal.
  • pushd y popd Cambian el directorio de trabajo recordando en cual estábamos antes y regresan al directorio anterior respectivamente.
  • pwd Nos dice cual es nuestro directorio de trabajo.
  • ls nombre_de_ruta Muestra el contenido del directorio, si no indicamos ningún nombre muestra el contenido del directorio de trabajo, con un nombre de fichero nos sirve para saber si el fichero existe o no.
  • tree [-d] nombre_de_ruta_de_directorio Muestra el contenido del directorio y de los directorios hijos en forma de árbol, si no indicamos ningún nombre muestra el contenido del directorio de trabajo, con el parámetro -d sólo muestra los directorios, sin el muestra directorios y ficheros. (Tree no está instalado por defecto en todas las distribuciones)
  • touch nombre_de_fichero Si el fichero no existe lo crea vacío, si existe simplemente le cambia la fecha de modificación por la del momento en que hacemos el touch, pero sin modificar ninguno de sus datos.
  • cp fichero1 fichero2 Copia el fichero uno al fichero2 si fichero2 no existe lo crea, si ya existía machaca todo su contenido.
  • cp fichero1 fichero2 (etc..) directorio Copia todos los ficheros que le digamos al directorio especificado.
  • mv Funciona exactamente igual que cp, solo que mueve los ficheros en vez de copiarlos, (es decir el fichero original se borra), sirve también para renombrar.
  • rm fichero [fichero2 …] Borra el o los fichero especificado.
  • cat fichero [fichero2 …] Muestra el contenido del o los fichero.
  • more fichero Nos permite ver el contenido de un fichero largo que no cabe en pantalla e ir pasando página a página.
  • less fichero Nos permite ver el contenido de un fichero, y desplazarnos por él arriba y abajo.
  • file fichero Examina el fichero para identificar cual es su contenido, nos dice si es una imágen, un vídeo, un archivo de texto, etc…
  • locate fichero_o_directorio Busca un directorio o un fichero en el disco.
  • du Obtiene información sobre lo que ocupa un fichero o directorio en el disco.
  • df Obtiene información sobre el espacio que nos queda libre en nuestro(s) disco(s).
  • basename Dado un nombre de ruta de fichero quita toda la parte del directorio dejándo solamente el nombre del fichero.
  • dirname Dado un nombre de ruta de un directorio quita el nombre del fichero dejándo solamente la ruta del directorio.

Editar ficheros de texto

Muchas veces, y por muy diversas razones tendremos la necesidad de editar ficheros de texto. En este curso pronto empezaremos a crear nuestros propios scripts que no son más que archivos de texto, y necesitaremos editarlos. En linux existen multitud de editores de texto tanto gráficos como de consola, y no voy a ser yo quien os diga cual debéis utilizar, el que prefiera uno gráfico tiene gedit en Gnome, kate en Kde, mousepad en xfce. Cualquier escritorio de linux cuenta entre sus utilidades con un editor de textos.

El que quiera un editor gráfico específicamente pensado para programadores tiene el scite, NEdit… La ventaja de estos es que reconocen la sintáxis de diversos lenguajes de programación y resaltan en colores los distintos elementos para que nos sea más sencillo programar, formatean el texto para que sea más sencillo identificar el principio y el final de ciertos bloques de código, o incluso permiten plegar y desplegar bloques (scite), todo ello hace que sean más cómodos para la tarea de editar scripts y programas.

Siendo como soy un amigo de la consola, lo que yo os aconsejaría sería un editor de texto que funcione en la propia consola, sin necesidad de entorno gráfico. Y no voy a entrar en una discusión sobre vi contra emacs, porque aunque los conozco no utilizo habitualmente ninguno de los dos. Yo personalmente uso joe, nano puede ser una buena opción, ne está muy bien y es sencillo de utilizar. Otro editor sencillo de usar es el mcedit, que viene con el midnight commander.

wpe (y xwpe) es un editor de texto que se acerca bastante a los editores gráficos de hecho son dos programas uno para consola de texto y otro para entorno GUI ambos prácticamente con el mismo aspecto, inicialmente estaba pensado para C pero se pueden descargar extensiones con la sintáxis de otros lenguajes (bash inclído).

Vistas las opciones (y no sólo las que yo te he contado), elige el que quieras, lo importante es que estés cómodo con él, y que sepas manejar las funciones básicas abrir un fichero guardarlo, buscar texto, cortar, pegar…