SDB:Funtamentos de bash

Saltar a: navegación, buscar


Artículos recomendados Artículos relacionados
Icon-manual.png Icon-ayuda.png

Introducción

Aunque es posible usar un sistema operativo cualquiera con éxito sin usar jamás un terminal de comandos, lo cierto es que conocer su uso básico favorece el aprendizaje de algunos conceptos. El ámbito de este documento es orientar al usuario en el uso de comandos básicos que le servirán para dicho aprendizaje. Para aquellas personas usuarias interesadas en aprender un mejor uso del terminal se recomienda consultar obras más detalladas sobre Bash y en particular sobre su programación.

El intérprete

El shell bash, que es el que acompaña por defecto a la mayoría de distribuciones de Linux, es lo que se denomina un intérprete de comandos. Eso significa que la persona usuaria interactúa con el sistema proporcionando comandos determinados que el intérprete procesa.

Los escritorios gráficos de Linux proporcionan aplicaciones que permiten utilizar el intérprete de comandos desde la propia sesión gráfica. El escritorio Plasma proporciona konsole para esta labor[1].

El terminal en el que ejecutamos bash es una pantalla o ventana de texto. El intérprete proporciona un prompt. Por defecto, en openSUSE está formado de la siguiente manera:

usuario@máquina:~>
  • usuario es tu nombre como usuaria.
  • @ es un separador de forma similar a las direcciones de correo-e.
  • máquina es el nombre que le hayas asignado a tu máquina. Normalmente el sistema asigna un nombre más o menos arbitrario durante la instalación, pero puedes cambiárselo.
  • : es otro separador.
  • ~ es una abreviatura para representar tu carpeta personal. Normalmente, a medida que te mueves por el árbol de directorios, esto se sustituye por tu ubicación actual.
  • > es otro separador.

Cuando está visible este prompt en la última línea, significa que puedes introducir un comando. Por ejemplo, puedes ejectuar konsole o el terminal de tu escritorio gráfico, e introducir el siguiente comando para saber la ruta hasta donde estás:

gecko@Leap-PC:~> pwd
/home/gecko
gecko@Leap-PC:~>

Al ejecutar konsole se ejecutará automáticamente el intérprete de comandos que tengas configurado y que por defecto en openSUSE es Bash.

El uso del escritorio desarrollado por Microsoft para su sistema operativo Windows ha extendido el uso del término folder (carpeta) en lugar de directory (directorio) y en mi opinión está bien. Es una metáfora muy visual: guarda ese fichero en la carpeta del proyecto. No obstante, en el mundo del terminal suele usarse directorio y de hecho la nemotecnia de los comandos empuja a ello: change directory (cambiar directorio) para el comando cd, que permite justamente acceder a un directorio. No hay nada malo en usar carpeta, pero la mayoría de textos que leas sobre el terminal emplearán directorio. Consulta la sección Carpetas para ver las diferencias.

Dialogo informacion 64x64.png

Los comandos del sistema tienen una página de manual que por desgracia no se ha traducido en años y que rara vez tendremos en castellano. Sin embargo, los comandos que ejecutaremos aquí son muy sencillos y pueden entenderse facilmente en inglés. Si deseas ver información del comando en castellano, puedes usar un buscador web con man comando español. Por ejemplo, man pwd español.

El prompt suele incluir, y en openSUSE es así por defecto, el nombre como usuaria del sistema. Pero esto no es así para la cuenta administradora (root), que se resalta en rojo, o puede que se haya establecido otra configuración. En cualquier caso, hay un comando para comprobar qué cuenta usuaria estás utilizando en ese momento: whoami, en inglés, literalmente, ¿quién soy?

gecko@Leap-PC:~> whoami
gecko
gecko@Leap-PC:~>

En una sesión gráfica, el terminal en el que ejecutas bash, como konsole, se denomina terminal virtual. Una verdadera sesión con el intérprete de comandos requiere hacerlo en modo texto y comenzará con el login, en el que se ha de introducir el nombre y la contraseña. En este documento se asume el uso de un terminal virtual, normalmente konsole.

Dialogo informacion 64x64.png

La sesión con el intérprete bash concluye al ejecutar el comando exit o bien al cerrar konsole.

Es posible ejecutar distintos intérpretes de comandos dentro de una sesión con bash, incluso el propio bash. De hecho, eso es lo que sucede cuando se cambia de usuario con el comando su y el modificador -:

gecko@Leap-PC:~> su -
Leap-PC:~ #

El símbolo # es habitual en el prompt del administrador. Hay mucha documentación donde el verás que el símbolo $ corresponde a las cuentas usuarias regulares, y # al administrador, y se omite el resto del prompt, de esta forma:

$ whoami
tux
# whoami
root

Procesos

Aunque la idea de usar un intérprete de comandos es interactuar con el sistema mediante los susodichos comandos, en muchas ocasiones será interesante ejecutar un comando y dejar que se ejecute en segundo plano hasta que finalice. Por ejemplo, el comando cp que se verá en la sección #Copia con cp puede ejecuarse en segundo plano añadiendo el símbolo ampersand al final del comando:

gecko@Leap-PC:~> cp -r un_directorio_con_muchos_ficheros otra_carpeta &
gecko@Leap-PC:~>

En lugar de mostrar el proceso del comando, inmediatamente devuelve el prompt para poder seguir introduciendo comandos. Es posible que a veces el comando en ejecución muestre de todas formas qué está haciendo, pero incluso así seguiremos teniendo el control del prompt para introducir otros comandos.

En ocasiones podrá suceder que ejecutamos comandos largos sin el ampersand y nos vemos en la necesidad de interrumpirlo para ejecutar otros comandos distintos. Eso lo podemos hacer pulsando CTRL+C (la combinación general para interrumpir un comando).

También es posible que querramos pasar a segundo plano el comando, lo que podemos hacer pulsando CTRL+Z. Eso normalmente detendrá la ejecución de ese comando y nos dará el control del prompt. Para continuar con la ejecución del programa detenido, ejecutaremos el comando fg.

kill es un comando que nos permite enviar señales a un comando que esté en ejecución. Esas señales pueden ser, por ejemplo, detenerse, o directamente matarse (interrumpirse por completo), y en general se emplea pasando la opción numérica correspondiente (9 para matar un proceso, 15 para detenerlo). killall permite matar procesos pero indicando el nombre del proceso, en lugar de su número de proceso (UID). ps es un comando que lista los procesos en ejecución.

Uso de intérpretes de comandos en bash

Hay muchos lenguajes de programación y aplicaciones específicas que proporcionan intérpretes de comandos: bases de datos, calculadoras, lenguajes interpretados... Si aun estás en la sesión con el administrador (prompt en rojo acabado en #), escribe exit para volver a la sesión de usuario y ejecuta la calculadora integrada con el comando bc (ejecuta man bc para aprender más sobre ella):

gecko@Leap-PC:~> bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.

bc no usa prompt y puedes escribir las expresiones a calcular directamente. Por ejemplo, para calcular la suma 5+3 basta con escribirlo y pulsar intro:

5+3
8

Para salir, basta con escribir quit (quitar el programa):

quit
gecko@Leap-PC:~>

Moviéndote por el árbol de directorios

Cada directorio, salvo la raíz, contiene dos ficheros especiales, denominados . (punto) y .. (dos puntos). El fichero . hace referencia al directorio actual y el fichero .. hace referencia al directorio anterior o padre.

Para poder desplazarte por los directorios del sistema tienes el comando cd (change directory). Al comando le proporcionas el lugar al que quieres desplazarte, de la siguiente forma:

  • cd ruta_directorio te desplaza al directorio de nombre ruta_directorio
  • cd .. te desplaza al directorio padre del actual.
  • cd . no tiene efecto porque te desplaza al directorio actual.

El signo / se emplea como separador entre directorios con el significado padre de. En dir_padre/dir_hijo, dir_hijo es un directorio que está dentro de dir_padre, de forma que dir_padre es el directorio padre de dir_hijo.

Dado que el directorio raíz root no tiene padre, se representa únicamente con la barra espaciadora. De esta forma, para desplazarnos desde cualquier lugar hasta el directorio raíz, basta con ejecutar:

gecko@Leap-PC:~> cd /
gecko@Leap-PC:/>

Existen dos tipos de rutas a directorio: las rutas que incluyen toda la ruta desde el directorio raíz, llamadas rutas absolutas y las rutas que incluyen un origen en un directorio dado, llamadas rutas relativas. Normalmente las rutas relativas comenzarán en un directorio dentro de nuestro directorio actual.

gecko@Leap-PC:/> cd /home/gecko
gecko@Leap-PC:~>

El comando cd /home/gecko nos devuelve al directorio del usuario gecko. Por su parte

gecko@Leap-PC:~> cd Documentos
gecko@Leap-PC:~/Documentos>

Nos lleva al directorio Documentos dentro del directorio del usuario gecko. En ese punto, para volver al directorio del usuario tenemos tres opciones:

gecko@Leap-PC:~/Documentos> cd ..
gecko@Leap-PC:~>
O bien
gecko@Leap-PC:~/Documentos> cd
gecko@Leap-PC:~>

O bien

gecko@Leap-PC:~/Documentos> cd ~
gecko@Leap-PC:~>

Usar cd sin argumentos te llevará siempre al directorio de usuario. Por su parte, la virgulilla es una abreviatura de bash y significa el directorio del usuario. Puede utilizarse de forma absoluta, formando rutas como ~/Documentos, o bien como atajo con el comando cd. Esto permite que, por ejemplo, para cambiar desde Documentos hasta Descargas, puedas ejecutar:

gecko@Leap-PC:~/Documentos> cd ~/Descargas
gecko@Leap-PC:~/Descargas>

Bash tiene un montón de atajos y facilidades, y la instalación por defecto de openSUSE Leap añade muchos más. Por ejemplo, dentro de Descargas escribe: cd ../ y pulsa la tecla tabulador (TAB) un par de veces:

gecko@Leap-PC:~/Descargas> cd ../

Pulsa el tabulador dos veces, y verás lo siguiente (puede haber otros directorios en tu sistema):

.cache/     .config/    Descargas/    Documentos/    Escritorio/    Imaxes/    .local/     logs/    Modelos/    Música/    Público/    Vídeos/

Al pulsar el tabulador, bash trata de autocompletar la ruta desde el texto que hayas escrito justo antes. ../ significa desde el directorio anterior y te proporcionará todas las opciones. Si escribes una D mayúscula[2] y vuelves a pulsar el tabulador, te ofrecerá todas las opciones que comienzan con D (Documentos y Descargas, salvo que tengas algún directorio más en tu sistema que también empiece por D).

Esta forma de autocompletar es muy cómoda, pero tiene sus cosas. Si pulsas una vez el tabulador, sólo funcionará si hay una sola opción disponible. Por ejemplo, cd ../Doc se autocompletará como cd ../Documentos/[3]. Si no hay una única opción, volver a pulsarlo mostrará todas las opciones disponibles que coincidan con ese patrón. Si tienes un directorio llamado Proyectos dentro de Documentos, puedes hacer lo siguiente para acceder a él: cd ~/Do<tabulador>Pr<tabuldador> (escribir cd, espacio, virguilulla, barra de división, Do, tabulador, Pr, tabulador. Lo cual irá autocompletando cd ~/Documentos/Proyectos. Una vez tienes todo el comando, basta con pulsar intro para ejecutar el comando.

Trabajando con ficheros

Desde el punto de vista de Linux, cualquier cosa que no sea la red, es un fichero. Según el cometido de ese fichero, puede ser de diferentes tipos:

  • Ficheros regulares.
    • Ficheros de texto.
    • Ficheros binarios.
    • Directorios.
  • Enlaces blandos.
  • Enlaces duros.
  • Dispositivos.
    • de bloques.
    • de caracteres.

Listar ficheros

El comando usual para listar el contenido de un directorio, y ver así qué ficheros o directorios contiene, es ls.

gecko@Leap-PC:~/Documentos> ls
script.sh

ls es un comando que admite un buen montón de argumentos. Los más habituales son:

  • l para visualizar un listado largo, que incluye información de cada fichero o directorio tal como su propietario y permisos.
  • d para listar el directorio en lugar de su contenido. Es común usarlo con el argumento l.
  • a para listar los ficheros incluyendo los ficheros ocultos. En Linux, un fichero está oculto cuando su nombre comienza por . (punto).

Para usar estas opciones, ls ha de ir seguida por el carácter guión -, por ejemplo, para obtener un listado largo:

gecko@Leap-PC:~/Documentos> ls -l
-rw-r--r-- 1 gecko users 31 Mar  1 17:51 script.sh

Aunque es posible poner cada opción con su propio guión, lo habitual es agruparlos. Así, los siguientes dos comandos tienen el mismo resultado:

gecko@Leap-PC:~/Documentos> ls -l -a
total 12
drwxr-xr-x  2 gecko users   22 Mar  1 18:29 .
drwxr-xr-x 14 gecko users 4096 Mar  1 18:28 ..
-rw-------  1 gecko users  105 Abr 14 2021  .directory
-rw-r--r--  1 gecko users   31 Mar  1 17:51 script.sh
gecko@Leap-PC:~/Documentos> ls -la
total 12
drwxr-xr-x  2 gecko users   22 Mar  1 18:29 .
drwxr-xr-x 14 gecko users 4096 Mar  1 18:28 ..
-rw-------  1 gecko users  105 Abr 14 2021  .directory
-rw-r--r--  1 gecko users   31 Mar  1 17:51 script.sh

En el listado largo, cada fichero ocupa una fila. El primer grupo de caracteres empezará por d si es un directorio, - si es un fichero regular, b para un dispositivo de bloques, l para enlaces, b para dispositivos de bloques y c para dispositivos de caracteres.

Ficheros regulares

Los ficheros de texto contienen caracteres de texto, normalmente en código ASCII. En Linux son ampliamente usados, por ejemplo de forma preferente para los ficheros de configuración de casi cualquier elemento. Por su parte, los ficheros binarios tienen un contenido binario definido en función del tipo de fichero concreto. Los directorios son un tipo de fichero especial que permiten organizar los ficheros almacenados en el sistema de forma más adecuada para el uso por parte del usuario.

Para que un fichero regular sea ejecutable ha de cumplir con dos requisitos: tener permiso de ejecución para el usuario que quiere ejecutarlo[4], y contener código ejecutable de alguna clase. Por ejemplo, pwd es un fichero regular binario:

gecko@Leap-PC:~/Documentos> file /usr/bin/pwd
/usr/bin/pwd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5d7ba8d4e2d3bda8835aaf230b257e55009d8f1a, for GNU/Linux 3.2.0, stripped

Podemos probar qué sucede si creamos un sencillo script[5], que son ficheros de texto que contienen código de algún lenguaje interpretado, incluido bash. Para ello usaremos el comando cat (que permite leer ficheros de texto) de una forma particular. Una vez que introduzcas cat > script y pulses intro, podrás introducir las líneas de una en una (pulsando intro en cada una, incluso en las vacías). Una vez acabado, después de "Hola mundo!", pulsa la combinación CTRL+D:

gecko@Leap-PC:~/Documentos> cat > script.sh 
#!/bin/bash

echo "Hola mundo!"
gecko@Leap-PC:~/Documentos> file script.sh
script.sh: Bourne-Again shell script, ASCII text executable

Bourne-Again shell es el nombre completo de Bash, y literalmente dice que es un fichero que contiene un script de bash escrito con texto ASCII y que es ejecutable.

Para ejecutarlo no se requieren permisos de ejecución, basta con emplear algún intérprete de comandos adecuado, en este caso, bash.

gecko@Leap-PC:~/Documentos> bash script.sh 
Hola mundo
gecko@Leap-PC:~/Documentos> sh script.sh
Hola mundo
gecko@Leap-PC:~/Documentos>

sh es otro atajo, en esta ocasión nombra al intérprete de comandos configurado en nuestro sistema. En la instalación por defecto de openSUSE será bash, pero hay muchos más.

Enlaces y accesos directos

Enlaces blandos, simbólicos o accesos directos

Un enlace simbólico en realidad es un fichero que contiene la ubicación de otro fichero. En los sistemas gráficos suelen ser denominados accesos directos que es el nombre que popularizó Windows.

En linux un enlace simbólico no tiene nada particular.

gecko@Leap-PC:~/Documentos> echo "fichero original" > texto.txt
gecko@Leap-PC:~/Documentos> cat texto.txt 
fichero original
gecko@Leap-PC:~/Documentos> ln -s texto.txt texto.txt.ln
gecko@Leap-PC:~/Documentos> ls -l
total 8
-rw-r--r-- 1 karl users 17 Xan 24 11:11 texto.txt
lrwxrwxrwx 1 karl users  9 Xan 24 11:11 texto.txt.ln -> texto.txt
gecko@Leap-PC:~/Documentos> cat texto.txt.ln 
fichero original

Al hacer el listado con ln -l, en la primera columna la primera letra es "l", que nos indica que texto.txt.ln es un enlace simbólico. Al final de la línea se muestra el nombre del enlace simbólico y una flecha seguida del fichero (con su ubicación si es diferente) que al que se enlaza con esa entrada.

Distintos escritorios pueden tener procedimientos ligeramente diferentes para crear enlaces simbólicos. Consulta la documentación del tuyo al respecto. Por ejemplo, para hacerlo con Dolphin (Plasma): Copiar, mover_y_crear_enlaces_simbólicos.

Enlaces duros

Los enlaces duros han perdido popularidad con el auge de los escritorios gráficos. La idea es que las entradas de directorio son una forma de organizar los ficheros para los usuarios de la computadora. No existe ningún área de ningún disco que se delimite para formar una carpeta y guardar ficheros dentro de esa área. El sistema operativo utiliza distintos procedimientos para establecer dónde guarda cada fichero. Dicho fichero ni siquiera tiene por qué estar todo junto, sino que es posible que esté repartido en fragmentos a lo largo del disco. Cada tipo de sistema de ficheros, sea btrfs, ext4, xfs, etc., lo hace de una forma diferente.

De cara al usuario, los ficheros se guardan formando una jerarquía que permite relacionar los ficheros entre sí. Cuando operas con una entrada de un directorio dado, el sistema la traduce a la ubicación real del fichero y hace aquello que se haya indicado. Puedes pensar que cada entrada de directorio correspondiente a un fichero es un enlace entre ese fichero y el lugar real donde ser almacena el fichero. Así, cuando ejecutas cat script.sh el sistema consulta la entrada de script.sh y recupera el fichero real para mostrar su contenido por pantalla. En ese sentido, todos los ficheros regulares son enlaces duros.

Recuerda que los enlaces simbólicos son ficheros que contienen una ubicación. En ese sentido acceso directo a fichero (o directorio) es un nombre un poco más adecuado. En cambio, la herramienta para crear enlaces duros es la misma: ln, pero sin opciones. La sintaxis es la misma: ln fichero enlace

gecko@Leap-PC:~/Documentos> ln script.sh enlace_script.sh
gecko@Leap-PC:~/Documentos> ls -l
total 8
lrwxrwxrwx 1 gecko users  9 Mar  1 18:40 acceso_directo_a_script.sh -> script.sh
-rw-r--r-- 2 gecko users 31 Mar  1 17:51 enlace_script.sh
-rw-r--r-- 2 gecko users 31 Mar  1 17:51 script.sh

Como puedes observar, ahora hay un fichero llamado enlace_script.sh que es aparentemente igual a script.sh. Podríamos ejecutarlo con bash o leer su contenido con cat para comprobar que son iguales, aunque eso no diferencia un enlace duro de un enlace simbólico. Pero si te fijas en el listado obtenido con ls -l, verás que en la columna que va antes del nombre del usuario propietario del fichero, en lugar de un 1 como teníamos hasta ahora, hay un 2. Ese número representa el número de enlaces duros que tiene ese fichero: por defecto es 1, porque, como ya se ha dicho, todos los ficheros son en realidad enlaces duros de sí mismos.

Un uso habitual de los enlaces de cualquier tipo es hacer accesible el fichero como si formara parte de otro directorio. El comando mkdir (make directory, crear directorio) permite crear directorios.

gecko@Leap-PC:~/Documentos> mkdir carpeta
gecko@Leap-PC:~/Documentos> ln script.sh carpeta/script.sh
gecko@Leap-PC:~/Documentos> ls -l
total 8
lrwxrwxrwx 1 gecko users  9 Mar  1 18:40 acceso_directo_a_script.sh -> script.sh
drwxr-xr-x 2 gecko users 22 Mar  1 19:09 carpeta
-rw-r--r-- 3 gecko users 31 Mar  1 17:51 enlace_script.sh
-rw-r--r-- 3 gecko users 31 Mar  1 17:51 script.sh
gecko@Leap-PC:~/Documentos> ls -l carpeta/
total 4
-rw-r--r-- 3 karl users 31 Mar  1 17:51 script.sh

Ahora los tres ficheros, script.sh, enlace_script y carpeta/script.sh tienen un 3 en el número de enlaces duros. Como cada uno apunta al contenido del fichero en sí, cada entrada puede ser movida, renombrada o incluso eliminada sin afectar al resto de enlaces.

gecko@Leap-PC:~/Documentos> rm script.sh
gecko@Leap-PC:~/Documentos> ls -l
total 4
lrwxrwxrwx 1 karl users  9 Mar  1 18:40 acceso_directo_a_script.sh -> script.sh
drwxr-xr-x 2 karl users 22 Mar  1 19:09 carpeta
-rw-r--r-- 2 karl users 31 Mar  1 17:51 enlace_script.sh

Por un lado, al borrar script.sh el enlace simbólico vuelve a estar roto. Por otro lado, el 3 en las entradas de los enlaces duros ha sido sustituido con un 2, que es el número de enlaces duros que quedan para el contenido de script.sh. En la práctica, borrar un fichero consiste en tener 0 enlaces duros al mismo.

Y por supuesto, al modificar el contenido a través de cualquier enlace, obtenemos el mismo resultado con el resto de enlaces duros.

gecko@Leap-PC:~/Documentos> echo "echo y más allá!" >> carpeta/script.sh
gecko@Leap-PC:~/Documentos> bash enlace_script.sh
Hola mundo
y más allá!

Los enlaces duros no son apropiados para crear enlaces entre ficheros de distintos dispositivos ni entre directorios. Para estos casos, emplea enlaces simbólicos.

Eliminar directorios

Los directorios, además de accedidos con el comando cd y creados con el comando mkdir, pueden ser eliminados. Sin embargo, para el sistema no es lo mismo eliminar una entrada de directorio correspondiente a un directorio vacío, que una entrada de directorio correspondiente a un directorio que a su vez tiene ficheros o directorios en su interior.

gecko@Leap-PC:~/Documentos> mkdir dir1
gecko@Leap-PC:~/Documentos> ls
acceso_directo_a_script.sh  carpeta  dir1  enlace_script.sh
gecko@Leap-PC:~/Documentos> rmdir dir1
gecko@Leap-PC:~/Documentos> ls
acceso_directo_a_script.sh  carpeta  enlace_script.sh
gecko@Leap-PC:~/Documentos> rmdir carpeta
rmdir: error al eliminar 'carpeta': Directorio no vacío

Para eliminar directorios que contengan ficheros o directorios, se emplea el comando rm -r

gecko@Leap-PC:~/Documentos> rm -r carpeta/
gecko@Leap-PC:~/Documentos> ls
acceso_directo_a_script.sh  enlace_script.sh

Sin embargo, rm es un comando para ficheros. rm aplicado a un directorio vacío no funcionará sin el parámetro -r:

gecko@Leap-PC:~/Documentos> mkdir dir1
gecko@Leap-PC:~/Documentos> rm dir1
rm: no se puede borrar 'dir1': Es un directorio

Tradicionalmente el borrado de ficheros y directorios requería confirmación para cada directorio o fichero borrado. Para evitar tener que responder a la misma pregunta cada vez se solía utilizar el parámentro -f, siendo la forma más común de borrado recursivo rm -rf directorio. openSUSE por defecto no te pedirá confirmación salvo que cambies la configuración del comando, con lo que rm -r tendrá el mismo efecto que rm -rf.

Copiar y mover ficheros

En la sección #Enlaces duros hemos visto que un mismo fichero puede tener varios enlaces, de tal forma que al eliminar cualquiera de ellos aun permanecerían los demás, y por ende su contenido.

Copiar un fichero consiste en obtener dos enlaces a dos copias diferentes del mismo fichero. En algunos tipos de sistemas de ficheros modernos en realidad no se hará una copia del fichero hasta que se intente modificar uno de ellos, característica denominada cow (copy on write, copia al modificar). Usar cow o no es una cuestión que atañe al sistema operativo e indistinto desde el punto de vista del usuario. Por su parte, mover un fichero o directorio implica cambiar su ubicación hasta otro directorio.

Copia con cp

La forma más sencilla de obtener una copia de un fichero es con el comando cp. Su sintaxis es cp origen destino. No obstante, cp presenta similitudes con rm: no puede copiar directorios, vacíos o no. Para ocuparse de directorios, ha de usarse la opción -r.

gecko@Leap-PC:~/Documentos> echo "algún texto" > fichero1.txt
gecko@Leap-PC:~/Documentos> cp fichero1.txt fichero2.txt
gecko@Leap-PC:~/Documentos> cat fichero1.txt fichero2.txt
algún texto
algún texto
gecko@Leap-PC:~/Documentos> mkdir dir2
gecko@Leap-PC:~/Documentos> cp fichero2.txt dir2/
gecko@Leap-PC:~/Documentos> ls dir2/
fichero2.txt
gecko@Leap-PC:~/Documentos> cp dir2 dir3
cp: -r no especificado; omitiendo directorio 'dir2'
gecko@Leap-PC:~/Documentos> cp dir2 dir3 -r
gecko@Leap-PC:~/Documentos> ls
acceso_directo_a_script.sh  dir1  dir2  dir3  enlace_script.sh  fichero1.txt  fichero2.txt
gecko@Leap-PC:~/Documentos> ls dir3/
fichero2.txt

Cuando autocompletas con el tabulador se incluirá el separador /. El comando cp no actúa direfente con o sin barra de dividir, pero otros comandos que se verán a continuación pueden proporcionar resultados imprevistos.

Dialogo informacion 64x64.png

La mayoría de comandos aceptarán las opciones más o menos en cualquier lugar. Por ejemplo, ls -l dir1/ -a funcionará correctamente

Dialogo informacion 64x64.png
.

Copia con rsync

rsync es una versión moderna de cp, pero especializada en la copia a través de sistemas de ficheros en red e incluso mediante ssh. Tiene montones de opciones, muchas de las cuales dependen de qué se esté haciendo. Por ejemplo, -va hace una copia completa (recursiva, incluyendo enlaces, permisos...) mostrando lo que se está copiando. y -z habilita la compresión de lo que se copia (útil para copiar por la red).

Una de las particularidades de rsync es su habilidad para hacer copias incrementales. Una copia incremental consiste en que cada vez que copias dos cosas, sólo copias aquellas cosas que han cambiado desde la última vez.

gecko@Leap-PC:~/Documentos> rsync -va dir2/ dir1/
sending incremental file list
./
fichero2.txt

sent 143 bytes  received 38 bytes  362.00 bytes/sec
total size is 13  speedup is 0.07
gecko@Leap-PC:~/Documentos> ls dir1
fichero2.txt
gecko@Leap-PC:~/Documentos> echo "otro fichero más" >> dir2/fichero3.txt
gecko@Leap-PC:~/Documentos> rsync -va dir2/ dir1/
sending incremental file list
./
fichero3.txt

sent 173 bytes  received 38 bytes  422.00 bytes/sec
total size is 31  speedup is 0.15
gecko@Leap-PC:~/Documentos> ls dir1
fichero2.txt  fichero3.txt

Copia con dd

dd es una utilidad para copiar ficheros bit a bit y que se utiliza principalmente para hacer copias exactas de imágenes de discos (clones). Por ejemplo, podrías clonar tu partición /dev/sda2 en un fichero llamado sda2.img de la siguente forma: dd if=/dev/sda2 of=sda2.img.

Usar dd para copiar tus ficheros de un lugar a otro es un poco como matar moscas con misiles. Funciona, pero en general será más sencillo usar cp o rsync. Para hacer una copia de fichero2.txt podríamos usar el comando:

gecko@Leap-PC:~/Documentos> dd if=fichero2.txt of=fichero3.txt
gecko@Leap-PC:~/Documentos> cat fichero3.txt 
algún texto


Copia con cat

Muchas de las cosas que se pueden hacer en un terminal son en realidad efectos secundarios. Por ejemplo, el comando touch permite actualizar la hora de modificación de un fichero, pero su efecto secundario es que si no existe el fichero, lo crea con la fecha de modificación actualizada. Así que es ampliamente usado para crear ficheros vacíos.

cat muestra por pantalla el contenido de un fichero. Si redirigimos esta salida a un nuevo fichero, existente o no, tendremos una copia:

gecko@Leap-PC:~/Documentos> cat fichero1.txt > nuevo_fichero1.txt
gecko@Leap-PC:~/Documentos> cat nuevo_fichero1.txt 
algún texto

Podemos indicar un fichero, varios usando comodines, o una lista de ellos. La salida será mostrada en pantalla, la de cada fichero a continuación del anterior. Eso nos permite una forma sencilla de concatenar o unir ficheros:

gecko@Leap-PC:~/Documentos> cat fichero?.txt > nuevo_fichero_enésimo.txt
gecko@Leap-PC:~/Documentos> ls
acceso_directo_a_script.sh  dir1  dir2  dir3  enlace_script.sh  fichero1.txt  fichero2.txt  fichero3.txt  nuevo_dir  nuevo_fichero1.txt  nuevo_fichero_enésimo.txt
gecko@Leap-PC:~/Documentos> cat nuevo_fichero_enésimo.txt 
algún texto
algún texto
algún texto

Mover y renombrar con mv

'mv permite mover ficheros y directorios de una ubicación a otra.

gecko@Leap-PC:~/Documentos> mv nuevo_fichero_enésimo.txt dir1/
gecko@Leap-PC:~/Documentos> ls 
acceso_directo_a_script.sh  dir1  dir2  dir3  enlace_script.sh  fichero1.txt  fichero2.txt  fichero3.txt  nuevo_dir  nuevo_fichero1.txt
gecko@Leap-PC:~/Documentos> ls dir1/
fichero2.txt  fichero3.txt  nuevo_fichero_enésimo.txt

Y también permite renombrar ficheros y directorios:

gecko@Leap-PC:~/Documentos> mv dir1 directorio1
gecko@Leap-PC:~/Documentos> ls
acceso_directo_a_script.sh  dir2  dir3  directorio1  enlace_script.sh  fichero1.txt  fichero2.txt  fichero3.txt  nuevo_dir  nuevo_fichero1.txt

Esto puede ser un tanto confuso para el usuario recién llegado (y para el no tan reciente). Si existe el destino, mv moverá el origen al interior del destino:

gecko@Leap-PC:~/Documentos> mv dir2 dir3
gecko@Leap-PC:~/Documentos> ls dir3
dir2  fichero2.txt

Si existe un directorio con el nombre indicado en el destino, mv moverá el origen al directorio destino. Pero si renombras un fichero con el nombre de un fichero existente, ¡lo sobrescribirá!!

gecko@Leap-PC:~/Documentos> mv enlace_script.sh fichero1.txt
gecko@Leap-PC:~/Documentos> ls
acceso_directo_a_script.sh  dir3  directorio1  fichero1.txt  fichero2.txt  fichero3.txt  nuevo_dir  nuevo_fichero1.txt
gecko@Leap-PC:~/Documentos> cat fichero1.txt
#!/bin/bash

echo "Hola mundo"
echo y más allá!

Carpetas

En Linux se utiliza una aproximación interesante al concepto de carpeta. Algunos directorios contienen un fichero especial y oculto denominado .directory, que permite establecer configuraciones generales al utilizarse con ciertas aplicaciones.

gecko@Leap-PC:~/Documentos> cat .directory
[Dolphin]
PreviewsShown=true
SortOrder=1
SortRole=modificationtime
Timestamp=2022,3,1,19,58,21
Version=4

[Settings]
HiddenFilesShown=false

En este fichero de texto de configuración, los corchetes se usan para delimitar apartados. El primer apartado corresponde al gestor de ficheros Dolphin. Por ejemplo, indica que se muestren las previsualizaciones de los ficheros que contenga y la forma de ordenación al mostrar el contenido. El apartado Settings establece que cada vez que se muestre su contenido no se incluyan los ficheros ocultos.

Comodines

En Bash puedes usar un montón de comodines y abreviaturas. Por ejemplo, un asterisco * sustituye a cualquier conjunto de caracteres, mientras que un interrogante ? sustituye a un caracter. Por ejemplo:

gecko@Leap-PC:~/Documentos> ls dir?
dir1:

dir2:
fichero2.txt

dir3:
fichero2.txt
gecko@Leap-PC:~/Documentos> cp * dir1
cp: cannot stat 'acceso_directo_a_script.sh': Non hai tal ficheiro ou directorio
cp: -r no especificado; omitiendo directorio 'dir1'
cp: -r no especificado; omitiendo directorio 'dir2'
cp: -r no especificado; omitiendo directorio 'dir3'
gecko@Leap-PC:~/Documentos> ls dir1
enlace_script.sh  fichero1.txt  fichero2.txt
gecko@Leap-PC:~/Documentos> rm dir1/*
gecko@Leap-PC:~/Documentos> ls dir1/
gecko@Leap-PC:~/Documentos>

Conectores de comandos

Una de las cosas que hacen tan útiles a los terminales de comando son las distintas formas de interconectar unos comandos con otros.

Por ejemplo, puedes ejecutar un comando de forma condicionada a la ejecución de otro. Con && la condición es "si el comando ha sido válido" y con || la condición es "en cualquier caso". Por ejemplo:

gecko@Leap-PC:~/Documentos> mkdir nuevo_dir && cd nuevo_dir && touch hola.txt && cd ..
gecko@Leap-PC:~/Documentos> ls nuevo_dir/
hola.txt
gecko@Leap-PC:~/Documentos> mkdir nuevo_dir || cd nuevo_dir && touch nuevo_hola.txt && cd ..
mkdir: no se puede crear el directorio "nuevo_dir": El fichero ya existe
gecko@Leap-PC:~/Documentos> ls nuevo_dir/
hola.txt  nuevo_hola.txt

El segundo mkdir falla en su ejecución porque ya existe un directorio con ese nombre. Como la condición es O, la doble barra, los comandos siguientes se ejecutan. Si hubiera usado la condición Y, el doble ampersand, la ejecución se habría detenido ahí.

Otra forma de encadenar comandos es con tuberías. En la sección #Ficheros regulares se ha empleado una tubería >. Esta tubería hace que el resultado de ejecutar un comando, en aquel caso cat, sea introducido en el fichero que hay a su derecha. Literalmente, cat > fichero.txt hace que lo que vamos escribiendo en la pantalla sea enviado al fichero fichero.txt. Menos usual es la redirección inversa <. Esto hace que lo que está a la derecha sea enviado a lo que está a la izquierda.

gecko@Leap-PC:~/Documentos> cat < fichero1.txt 
algún texto
gecko@Leap-PC:~/Documentos> echo "más cosas" >> fichero1.txt
gecko@Leap-PC:~/Documentos> cat fichero1.txt 
algún texto
más cosas

Si usas un sólo signo > el resultado del comando de la izquierda sobrescribirá el fichero. Si usas dos signos >>, el resultado se añadirá al final.

Otra tubería popular es la barra vertical |, que permite que el resultado de ejecutar un comando con el resultado de otro comando. Por ejemplo, para buscar ficheros que contengan icher en su nombre, normalmente bastaría con ls *icher*, pero también podemos hacer eso como ejemplo:

gecko@Leap-PC:~/Documentos> ls *icher*
fichero1.txt  fichero2.txt
gecko@Leap-PC:~/Documentos> ls | grep icher
fichero1.txt
fichero2.txt

grep por defecto resaltará la cadena (conjunto de letras y signos) buscada. Por sí mismo es un comando que permite buscar cadenas de texto en ficheros de texto. Por ejemplo, para buscar qué fichero contiene la palabra algún:

gecko@Leap-PC:~/Documentos> grep algún *
grep: acceso_directo_a_script.sh: No existe tal fichero o directorio
grep: dir1: Es un directorio
grep: dir2: Es un directorio
grep: dir3: Es un directorio
fichero1.txt:algún texto
fichero2.txt:algún texto
grep: nuevo_dir: Es un directorio

Y con frecuencia se utiliza para hacer búsquedas en la salida de algún comando que proporcione un resultado largo. Por ejemplo, el comando ps lista los procesos en ejecución y es común listarlos con las opciones -aux. Para buscar el proceso konsole, podemos hacer lo siguiente:

gecko@Leap-PC:~/Documentos> 
ps aux | grep konsole
gecko      2549  0.0  1.0 694400 85380 ?        Sl   18:18   0:02 /usr/bin/konsole -session 10137156d2e4000164613515200000032360018_1646241240_34218
gecko     16848  0.0  0.0  10256  2456 pts/2    S+   19:05   0:00 grep --color=auto konsole

Los conectores no necesitan tener espacios en blanco alrededor, pero es buena idea para hacerlo más legible. En ese sentido, echo "hola" > fichero.txt es exactamente igual a echo "hola">fichero.txt

Notas

  1. En cualquier sistema gráfico pueden encontrarse estas aplicaciones buscando terminal.
  2. Linux distingue mayúsculas de minúsculas y es buena idea asumir que cualquier intérprete de comandos hará lo propio, aunque hay excepciones como algunos lenguajes de bases de datos, por ejemplo. En Bash, es diferente nombre de Nombre o de NOMBRE.
  3. Salvo en el caso de que existan otras carpetas que comiencen por Doc, como por ejemplo Documentanción.
  4. Para aprender sobre el uso de permisos de ficheros, consulta la guía Fundamentos del sistema de permisos
  5. Los scripts suelen traducirse literalmente como ficheros de guiones o en otras ocasiones como ficheros por lotes. Ambas expresiones hacen referencia al hecho de que ejecutan tareas de una en una.