Está en la página 1de 28

Capítulo 3: Herramientas de la línea de comandos, 1era parte

(Objetivos 103.1 a 103.4)


A pesar de que hoy existen distribuciones GNU/Linux con excelentes interfaces
gráficas, la línea de comandos nos ofrece herramientas de administración sumamente
útiles. Puede parecer intimidante al principio, pero con el tiempo puede convertirse
en nuestra mejor aliada. Además, este es el entorno más frecuente que encontraremos
en los servidores que administremos.

Entrada, salida, y error estándares


Cada vez que ejecutamos un comando, por lo general esperamos ver el resultado por
pantalla o guardar el mismo en un archivo. Hay ocasiones en que además del
resultado también se nos muestra cualquier error que se haya producido. Para
ilustrar, veamos en la imagen el resultado del comando
ls /boot /otrodirectorio

Como /otrodirectorio no existe, recibimos el mensaje de error que resaltamos.


Este ejemplo nos permite introducir el concepto de flujos de texto en Linux. En
palabras simples, un flujo de texto es una secuencia de bytes. Mediante estos, le
indicamos a un comando cómo operar (mediante el uso de opciones y argumentos a
través de la entrada estándar o stdin, por lo general representada por el teclado o por
la salida de otro comando) y recibimos el resultado (compuesto por la salida estándar
o stdout y el error estándar o stderr) en la terminal o lo redirigimos hacia a un archivo.
La entrada, salida, y error estándares están representados por un archivo dentro de
/dev y tienen asignado lo que se conoce como un descriptor de archivo (0, 1, o 2,
respectivamente) para identificarlos más fácilmente:
En la práctica utilizamos estos números cuando deseamos redirigir los flujos de texto:
• Para guardar el resultado de ls /etc en el archivo etc.txt dentro del directorio
actual podemos hacer:

ls /etc > etc.txt

o también
ls /etc 1> etc.txt

• Para enviar el contenido del archivo numeros.txt como entrada al comando sort
(que veremos más adelante en este mismo capítulo con más detalle), los dos
comandos siguientes son equivalentes:
sort < numeros.txt sort 0< numeros.txt

Por defecto, el operador > al ser empleado sin ningún otro modificador
asume 1>, de la misma manera que < es sinónimo de 0<.

• Volviendo a utilizar ls /boot /otrodirectorio, esta vez redirigiremos el


mensaje de error (utilizando el descriptor de archivo 2) a error.txt. El resto del
resultado se mostrará por pantalla como en el caso anterior:
ls /boot /otrodirectorio 2> error.txt

• Utilizando el ejemplo anterior también podemos guardar en ls.txt el resultado al


mismo tiempo que enviamos el error a error.txt como vemos en la imagen:
ls /boot /otrodirectorio 2> error.txt > ls.txt
• Finalmente, también podemos enviar tanto stdout como stderr al mismo destino.
Por lo general, si esperamos que un comando produzca una cantidad
considerable de salida (y/o error) que no deseamos ver en la terminal,
redirigimos ambos flujos al sumidero /dev/null:
ls /boot /otrodirectorio 2>&1 > /dev/null

En este último ejemplo, stderr (2) es redirigido a stdout (&1, donde & indica que 1
debe interpretarse como un descriptor de archivo en vez de un archivo propiamente
dicho llamado 1 a secas) y luego todo el conjunto es enviado a /dev/null.

La shell Bash y el entorno de trabajo


Al iniciar sesión nos aparecerá el bien conocido prompt con su shell o intérprete de
comandos asociado listo para nuestro uso.
Bash es un intérprete de comandos que ejecuta, una por una, las instrucciones
introducidas por el usuario o contenidas en un script y devuelve los resultados. En
otras palabras, actúa como interfaz entre el kernel Linux y los usuarios o programas
del modo texto. Además, incorpora numerosas utilidades de programación y mejoras
sobre sh, su shell predecesora. Debido a que es una herramienta desarrollada por
GNU, suele ser utilizada por defecto en las distros actuales.
Por otro lado, Bash no es una terminal. Tampoco es la única shell disponible. De
hecho, podemos ver los intérpretes disponibles en nuestro equipo al observar el
contenido del archivo /etc/shells. Si lo consideramos necesario, podemos asignar a
los usuarios comunes algún otro (distinto de Bash). De esta manera podemos
restringir el alcance de lo que pueden llegar a hacer utilizando la línea de comandos.
Por supuesto, es el administrador quien decide esto.

Variables de entorno
Una variable de entorno es un objeto que contiene datos utilizados por una o más
aplicaciones. En términos simples, se trata de un conjunto nombre/valor. Para ver la
lista de las variables disponibles en nuestra sesión de usuario utilizaremos el
comando env.
Algunas de ellas son las que mostramos en la lista siguiente, junto con su propósito. Es
importante aclarar que la disponibilidad de una cierta variable puede depender del
uso actual del sistema. Por ejemplo, SSH_CONNECTION no estará presente si no
estamos conectados a un servidor SSH remoto.
• HISTSIZE: máxima cantidad de comandos contenidos en el historial (aplica al
usuario logueado actualmente).

• USER: usuario actual.


• EDITOR: editor de texto por defecto.

• SHELL: shell configurada para el usuario actual.

• SSH_CONNECTION: detalles sobre la conexión SSH iniciada desde el equipo


actual. Presenta el siguiente formato: [IP del cliente] [puerto del cliente] [IP del
servidor] [puerto del servidor].

• PATH: listado de directorios, separados por dos puntos, donde se deben buscar
los ejecutables correspondientes a los comandos ingresados por el usuario.
En la imagen vemos los valores correspondientes a las variables mencionadas en el
listado anterior utilizando el comando echo y anteponiendo el signo $ al nombre de la
variable. Como podemos notar, no se ha establecido ningún valor para EDITOR.

Si deseáramos agregar el directorio ~/bin al final de PATH debemos hacer lo


siguiente:
PATH=$PATH:~/bin

o al principio:
PATH=~/bin:$PATH

La decisión de agregar un directorio al comienzo o al final de PATH


depende si queremos que sea examinado antes o después que el resto
de los directorios. Es importante tener en cuenta este punto si hay más
de un ejecutable con el mismo nombre en la lista de directorios
contenidos en PATH. Por ejemplo, si tanto ~/bin como /usr/bin
contienen un binario llamado id, será ejecutado el que aparece en
~/bin si este directorio se encuentra antes que /usr/bin en la lista.
Para que los cambios sean permanentes debemos agregar una de las líneas anteriores
al final de ~/.bash_profile o ~/.profile (en ese orden) y exportar la variable
precedidas por el comando export.
Lo que mencionamos en los párrafos anteriores también aplica para todas las
variables de entorno, no solamente para PATH.
Para ilustrar, establezcamos el valor de HISTSIZE en 2000. Notemos que usamos el
operador >> para agregar contenido al final del archivo en vez de > que provocaría el
efecto de sobreescribir sus contenidos.
echo 'HISTSIZE=2000' >> ~/.bash_profile

y luego indiquemos que la variable se deberá exportar al inicio de sesión del usuario
actual:
echo 'export HISTSIZE' >> ~/.bash_profile

Si deseamos que los cambios efectuados tomen efecto de manera inmediata podemos
utilizar el comando
source ~/.bash_profile

el cual ejecutará el contenido del archivo en cuestión.


Si hemos creado una variable de entorno personalizada (por lo general se le da un
nombre en MAYÚSCULAS) podemos destruirla con el comando unset:
LENGUAJE='Python'
echo $LENGUAJE
unset LENGUAJE
echo $LENGUAJE

En la imagen anterior vemos que luego de haber destruido la variable, esta ha


desaparecido de nuestro entorno.
Identificar comandos
Los muchos comandos que podemos llegar a utilizar se pueden clasificar en categorías
de acuerdo con su origen. Algunos de ellos están incorporados en la shell, mientras
que otros provienen de un determinado paquete que hayamos instalado. También
existe la posibilidad de que un comando sea en realidad un alias de otro comando con
sus opciones.

Un alias es un comando construido a partir de otros y/o diferentes


opciones, y es una manera de ejecutar una serie de comandos más
fácilmente. De esta manera, no es necesario recordar toda la secuencia
ni las opciones utilizadas.

Para empezar, ejecutemos los siguientes comandos en una terminal, cuyo resultado
vemos en la imagen siguiente:
• Un alias: type ls

• Una utilidad incorporada en la shell: type cd

• Un comando regular: type lscpu

En la imagen anterior podemos ver que ls es un alias de ls --color=auto, y que


lscpu corresponde a un ejecutable cuya ubicación es /usr/bin/lscpu. Esto significa
que cuando escribamos ls /mi/directorio en realidad estaremos ejecutando ls --
color=auto /mi/directorio.

Por supuesto, type acepta varias opciones que pueden modificar su uso. En primer
lugar, podemos mencionar -P, la cual obliga a una búsqueda dentro de los directorios
indicados en la variable de entorno PATH. Además, también podemos utilizar -a para
mostrar todas las coincidencias encontradas en los mismos.
Ahora veamos cómo crear alias para nuestro uso que se adapten a nuestros deseos o
necesidades.
Por ejemplo, el comando
cd ../../

se utiliza para retroceder dos directorios hacia arriba en la jerarquía de directorios a


partir del lugar actual. En cambio, podríamos escribir
alias ..='cd ../../'

y a partir de ese momento utilizar simplemente


..

cuando necesitemos desplazarnos de la misma manera que lo hacíamos antes con cd


../../.

Para deshabilitar un alias bastará utilizar la herramienta unalias seguida del nombre
del alias en cuestión:
unalias ..

Por otro lado, si deseamos que un alias sea permanente deberemos guardar su
declaración al final de ~/.bash_profile o ~/.profile.

El historial de comandos
Cuando iniciamos sesión en una terminal, el entorno de la shell se pone en
funcionamiento de acuerdo a nuestras configuraciones personales. Para cada usuario,
las mismas se encuentran dentro de archivos ocultos en su correspondiente directorio
personal. Uno de estos archivos es ~/.bash_history, donde se guarda el historial de
comandos en Linux.
Por suerte, al disponer del historial podemos ejecutar un comando fácilmente sin
volver a tener que escribirlo nuevamente. En primer lugar, recordemos que con el
comando history podemos listar los comandos disponibles. A continuación,
colocando un signo de exclamación y el número del comando en el historial podremos
ejecutarlo otra vez. En otras palabras,
history 10

devolverá los últimos 10 comandos ejecutados en la terminal actual, mientras que


!2006

repetirá type lscpu, como vemos en la imagen:


Si en vez de repetir de manera idéntica un comando del historial quisiéramos
modificarlo primero podemos utilizar fc, otra utilidad incorporada en la shell. Al
escribir
fc 2006

y presionar Enter. Como resultado, se abrirá nuestro editor de texto por defecto. Esto
nos permitirá modificar cualquier parte del comando y ejecutarlo automáticamente al
guardar los cambios.
Esta herramienta también nos permite modificar una serie de comandos y ejecutarlos
a continuación. Por ejemplo
fc 2000 20005

nos permitiría editar los comandos que ocupan desde la posición 2000 a la 2005 en el
historial.

Localizar comandos
El comando which nos muestra la ubicación del archivo ejecutable correspondiente a
un comando dado. Para hacerlo, busca en orden dentro de los directorios que
aparecen en PATH. Como podemos apreciar abajo, podemos indicarle más de un
comando a la vez:
which ls
which ps top
which whereis whatis man
Dos detalles interesantes sobre el uso de which son los siguientes:
• Una vez que se identifica un binario dado en un directorio incluido en PATH, la
búsqueda se detiene a menos que se utilice la opción -a. En ese caso se buscará
en TODOS los directorios en vez de finalizar con la primera ocurrencia.

• Si uno o más de los argumentos no se encuentra en PATH, which regresa un exit


status de 1. Si todos se encuentran, el exit status será igual a 0, mientras que será
igual a 2 si se especifica una opción no válida.
Los conceptos y comandos que hemos cubierto en esta sección nos servirán de base
para los contenidos del resto de este capítulo.

Manipulación de texto
Gran parte de las tareas de un sysadmin se llevan a cabo al manipular archivos o flujos
de texto. Para ayudarnos en esta responsabilidad podremos utilizar los comandos que
listamos a continuación.

Combinar archivos con cat y paginar con more o less


El comando cat es mayormente utilizado para mostrar por pantalla el contenido de
un archivo de texto corto. Sin embargo, como su nombre lo indica (concatenate)
también puede utilizarse para mostrar dos archivos o más, uno a continuación del
otro. Dos opciones útiles son --number (o su equivalente -n), la cual se utiliza para
mostrar los números de línea en la salida, y --squeeze-blank (o -s) que omite las
líneas vacías repetidas. En la imagen podemos ver el resultado del siguiente ejemplo:
cat archivo1.txt archivo2.txt -n -s
Otra alternativa para ver los números de línea junto a cada una es
utilizar la herramienta nl seguida del nombre del archivo a examinar,
produciendo esencialmente el mismo efecto de cat -n.

El comando cat puede ser interesante para ver el contenido de archivos pequeños,
pero en general more o less resultan de mayor utilidad en la mayoría de los casos, en
especial si tratamos con archivos extensos.
Estas dos herramientas paginan (dividen en páginas) uno o varios archivos y los
muestran en la terminal. De no indicárseles un archivo dado, paginan la entrada
estándar. Se diferencian en las facilidades que brindan como indicamos a
continuación:
• more es más restrictivo en cuanto al movimiento dentro del texto, y visualiza
sucesivamente el porcentaje del archivo examinado hasta el momento. Cuando se
alcanza el final del último archivo a paginar, more termina automáticamente.

• Por otro lado, less cumple la misma función que more, pero además, nos permite
realizar búsquedas de palabras dentro del contenido del archivo, resaltar los
resultados, y saltar entre una ocurrencia y otra.
Por ejemplo:
less /etc/password
more /etc/passwd
Para examinar un archivo (o más) con cualquiera de estas dos herramientas:
• la tecla q permite interrumpir el proceso y salir.

• /criterio realiza búsquedas del patrón criterio dentro del texto.


Para realizar otra búsqueda empleando un patrón distinto sólo es necesario escribir / seguido de la palabra
correspondiente.
• [n]b permite regresar n páginas (por defecto, n=1).

• [n]f es para adelantar n páginas.

• h para mostrar la ayuda disponible (también salimos de la misma con la tecla q).

Además, en less podemos emplear:


• G para desplazarnos al final del archivo.
• g para ir directamente al principio del archivo.

El comando man (que utilizamos para acceder a los man pages o manuales de los
comandos), utiliza por defecto el paginador less para dar formato a su salida. Existen
además los comandos zless y zmore que permiten paginar a los archivos
comprimidos sin necesidad de descompactarlos previamente en nuestro disco.

Ordenar líneas con sort


Si disponemos de registros en un archivo de texto que necesitaremos procesar, el
comando sort nos servirá de gran utilidad. Por defecto, esta herramienta ordena por
valor ASCII, por lo que diferencia entre minúsculas y mayúsculas. Además, utiliza
espacios para delimitar campos, y de no especificarse otra cosa, el orden se realizará a
partir del primer campo del archivo.
Veamos algunas opciones útiles que no son tan conocidas:
• -M o --month permite ordenar por mes a partir de las tres primeras letras del mes
en inglés (comenzando en JAN para enero y DEC para diciembre).

• -f o --ignore-case permite ignorar la diferencia entre mayúsculas y minúsculas.

• -t o --field-separator nos permite especificar un separador de campos


distinto al espacio.

El siguiente ejemplo, cuyo resultado se muestra en la imagen, ilustra el uso de las


opciones anteriores utilizando la coma como separador de campos. El mismo utiliza
un archivo llamado ejemplosort.txt con los contenidos mostrados en la misma
imagen:
sort -M -f -t, ejemplosort.txt
Por lo general, sort se utiliza junto con uniq, que permite eliminar líneas repetidas en
una secuencia. Por ejemplo, el comando
cat datos.txt | sort | uniq

o su equivalente
sort -u datos.txt

ordenará las líneas del archivo datos.txt omitiendo cualquier repetición presente.

Unir archivos línea a línea con paste


En el caso de que tengamos dos o más archivos que necesitemos unir línea a línea
(para procesar el resultado posteriormente), podemos emplear el comando paste.
Para ilustrar, tomemos los archivos paises.txt y capitales.txt que tienen los
siguientes contenidos:
En paises.txt:
Argentina
Uruguay
Paraguay
Chile
Bolivia
Brasil

En capitales.txt:
Buenos Aires
Montevideo
Asuncion
Santiago
La Paz
Brasilia

Para unir ambos archivos en un tercero llamado info.csv utilizando una coma para
separar campos, haremos
paste -d, paises.txt capitales.txt > info.csv

cuyo resultado es el que vemos en la imagen:

Esta herramienta siempre nos será útil cuando necesitemos pegar el contenido de un
archivo en otro y especificar un separador entre ambos. Los archivos con campos
separados por comas generalmente son empleados para procesar datos a través de un
programa de hojas de cálculo como Microsoft Excel o LibreOffice Calc.

Mostrar el comienzo o el fin de un archivo con head o tail


En algunas ocasiones (por ejemplo, al inspeccionar los primeros o últimos eventos
registrados en un log) nos puede interesar mostrar las primeras o las últimas líneas
de un archivo, lo cual podemos hacer con los comandos head o tail. Sin argumentos,
estas dos herramientas nos permitirán visualizar las primeras o últimas 10 líneas de
un archivo, respectivamente. También podemos utilizar la opción -n para cambiar la
cantidad de líneas.
Por ejemplo,
head -n 7 /etc/passwd

nos mostrará las primeras 7 líneas de /etc/passwd, mientras que


tail /etc/passwd

devolverá las últimas líneas del mismo archivo.


En particular, tail puede emplearse para visualizar las modificaciones a un archivo a
medida que se hacen. En otras palabras
tail -f /var/log/httpd/access_log

nos permitirá ver los accesos a nuestro servidor web Apache a medida que ocurran
(esta ruta corresponde a CentOS 7).

Mostrar campos separados por un delimitador


Muchas veces nos podemos encontrar con la necesidad de mostrar sólo algunos
campos de un archivo de texto en el que cada línea se encuentra dividida en dos o más
por un delimitador. Por ejemplo, el primer y el séptimo campo de /etc/passwd
muestran el nombre de los usuarios y su shell asignada, de haber una. El comando cut
nos permite mostrar esta información con facilidad, donde la opción -f nos permite
indica qué campos deseamos que se devuelvan, mientras que -d especifica el caracter
utilizado para separarlos:
cut -d: -f1,7 /etc/passwd

Otras situaciones en las que el uso de cut puede resultarnos útil es al extraer una
cierta cantidad de caracteres (mediante la opción -c) de cada línea. Podemos
especificar un rango definido, una posición de comienzo e indicar que se extraiga
hasta el final, o una posición final y pedir que se muestre desde el principio hasta la
misma:
• Para extraer los primeros 4 caracteres de cada línea: cut -c1-4 /etc/passwd

• Para mostrar desde el caracter en la posición 10 hasta el final de cada línea: cut
-c10- /etc/passwd

• Para ver desde el principio de cada línea hasta la posición 7: cut -c-7
/etc/passwd

Vale la pena recordar que el comando cut puede aceptar como entrada el resultado de
un comando anterior a través de una tubería. Por ejemplo,
date | tr -s " " | cut -d' ' -f6

devolverá el año actual a partir de date (que devuelve la fecha), tr (que a partir de la
opción -s remueve los espacios repetidos y los combina en uno), y de cut. Estos
comandos combinados nos permiten mostrar la información de interés.

Contar palabras, bytes, y líneas con wc


Una de las tareas más usuales con las que podemos encontrarnos es la necesidad de
contar la cantidad de líneas de un archivo o del resultado de un comando. Esto puede
bien representar la cantidad de cuentas de usuario del sistema (una por línea en el
archivo /etc/passwd) o la cantidad de archivos resultantes de una búsqueda con
find, por nombrar dos casos emblemáticos. En Linux disponemos de una herramienta
llamada wc para esto.
Utilicemos el archivo capitales.txt para ilustrar:
• Contar la cantidad de líneas: wc -l capitales.txt

• La cantidad de palabras: wc -w capitales.txt

• El número de caracteres, que debería coincidir con el tamaño del archivo: wc -c


capitales.txt

Si bien en este caso utilizamos un archivo propiamente dicho como argumento,


también podemos emplear una tubería para enviar la salida de un comando como
entrada a wc. Por ejemplo,
ps -u www-data | grep -v PID | wc -l

nos indicará cuántos procesos están corriendo bajo el usuario www-data. (Pista: grep
-v PID se utiliza para no incluir el encabezado de la lista de procesos en el conteo de
líneas).

Compresión de archivos y lectura de archivos comprimidos


Para comprimir archivos podemos utilizar cualquiera de las tres herramientas
siguientes: gzip, bzip2, o xz. Como parte del proceso de compresión, se reemplazará
el archivo original datos.txt por su versión comprimida. Los nombres de los archivos
comprimidos finales serán iguales a los iniciales, con la diferencia de que se agregarán
las extensiones .gz, .bz2, y .xz, respectivamente:
gzip datos.txt
bzip2 datos.txt
xz datos.txt

Para leer el contenido del archivo, podemos descomprimirlo para recuperar el


original, o bien utilizar los comandos zcat, bzcat, o xzcat para acceder al mismo
todavía comprimido:
gzip -dc datos.txt.gz
zcat datos.txt.gz
bzip2 -dc datos.txt.bz2
bzcat datos.txt.bz2
xz -dc datos.txt.xz
xzcat datos.txt.xz

La opción combinada -dc indica que se debe mostrar el resultado por pantalla en vez
de guardar el archivo descomprimido en el disco. Si se desea almacenar el archivo
original, tendremos que omitir la opción c:
gzip -d datos.txt.gz
bzip2 -d datos.txt.bz2
xz -d datos.txt.xz
Dividir archivos
Linux provee una herramienta muy útil llamada split para dividir archivos de gran
tamaño. Comencemos primero creando un archivo llamado archivoprueba.iso de 2 GB
(bs=1M * count=2000) en el directorio actual:
dd if=/dev/zero of=archivoprueba.iso bs=1M count=2000

En este ejemplo suponemos que deseamos dividir el archivo de 2 GB en partes de 600


MB como máximo. Debido a que 2 GB no es un múltiplo de esta cantidad, el último
archivo tendrá menor tamaño.
split --bytes 600M --numeric-suffixes archivoprueba.iso archivoprueba.iso
.

Con la opción --bytes indicamos el tamaño máximo que deberá tener cada archivo
individual. Por otra parte, --numeric-suffixes nos permite agregar un número al
final del nombre de cada uno. Finalmente, archivoprueba.iso es el nombre del
archivo a dividir, mientras que archivoprueba.iso. (notar el punto al final) es el
prefijo de salida.

Una vez que hayamos compartido los archivos, podemos regenerar el original muy
fácilmente. Nombraremos el archivo destino como archivoprueba.iso.nuevo para
distinguirlo del original propiamente dicho:
cat archivoprueba.iso.* > archivoprueba.iso.nuevo

A continuación, podemos comparar archivoprueba.iso con


archivoprueba.iso.nuevo utilizando el comando cmp:
cmp archivoprueba.iso archivoprueba.iso.nuevo
Si el comando anterior finaliza con código de salida igual a 0 (como en este caso, que
podemos comprobar con echo $?) significa que ambos archivos son iguales byte a
byte.
Es importante aclarar que, en este ejemplo trivial, con archivos creados a partir de
/dev/zero, partes individuales de igual tamaño mantendrán esta igualdad.

Validar integridad de archivos


En una época en que es común distribuir archivos a través de Internet (sea en forma
de descargas o a través de correo electrónico) es importante asegurarnos de que el
mismo no ha sido modificado en el camino por un atacante malicioso.
Para hacerlo, el dueño o remitente del archivo puede proveer un hash que representa
el contenido de este. Los dos algoritmos más utilizados son sha256 y sha512,
mientras que md5 (inventado a comienzos de la década de 1990) se considera
obsoleto.
Los siguientes comandos utilizan sha256sum, sha512sum, y md5sum para devolver el
hash que representa el contenido de datos.txt:
sha256sum datos.txt
sha512sum datos.txt
md5sum datos.txt

En la imagen anterior podemos apreciar el resultado. Podemos contar con que es


imposible (prácticamente hablando) que dos archivos diferentes tengan hashes
iguales.

Creación y manipulación de archivos y directorios


Para organizar nuestros archivos, poder montar dispositivos de almacenamiento, y
borrar contenido que no sea necesario es preciso que desde un comienzo sepamos
cómo emplear las herramientas que nombraremos en este apartado.

El comando ls
Este comando nos permite distinguir los siguientes tipos de contenidos en un
directorio. También vale la pena mencionar que si el argumento representa un
archivo, enlace simbólico, dispositivo, etc., veremos datos sobre el mismo en la salida
de ls.
• En blanco (en el caso de que el color de fondo de la terminal sea negro u otro
color oscuro, que es lo más común), los archivos de texto o binarios no
ejecutables.

• En verde, los archivos de texto (scripts) y otros binarios ejecutables.

• En celeste, los enlaces simbólicos.

• En fondo negro con letras rojas, los enlaces simbólicos rotos. Nos referimos a
aquellos que apunten a un recurso del sistema que no existe.

• En amarillo, los dispositivos de bloques.


• En violeta, los archivos de imágenes o archivos temporales.

• En rojo, los archivos comprimidos.


En la imagen siguiente podemos distinguir algunos de los casos que nombramos
arriba. En el primero, vemos que el archivo en cuestión se muestra en texto negro
debido a que el color de fondo de la terminal es un tono claro.

En este caso, adm.txt y datostutor.txt son ejemplos de archivos. Por otro lado,
archivo3 (contrario a lo que podría sugerir su nombre) se trata de un directorio,
link_archivo2 es un enlace simbólico activo, link_archivo1 uno roto, y archivo2 es
un archivo binario ejecutable.
En Linux podemos ver que tanto los archivos como los directorios pueden tener
varios puntos en su nombre, pero cuando el punto está adelante los transforma en
ocultos. Por ejemplo, .hola no se verá con un ls normal. Sin embargo, al utilizar el
modificador -a, podremos ver todos los archivos ocultos que se encuentran en ese
directorio.
Generalmente los archivos ocultos son los que contienen información
acerca de configuraciones. Al no ser visibles fácilmente es menos
probable que sean borrados de forma accidental.

Para ilustrar, veamos la diferencia que existe entre hacer ls y ls -a en el directorio


personal de un usuario.

Si ahora agregamos el modificador -l obtenemos mayor información de los archivos y


directorios. La salida del comando en este caso está dispuesta en columnas para que
nos resulte más sencillo reconocerla. Veamos cómo queda cada columna:
1. El primer caracter que aparece en la primera columna indica si lo que estamos
viendo es un archivo (-), un directorio (d), un enlace simbólico (l), o un
dispositivo de bloques (b), por nombrar algunos ejemplos. A continuación, vemos
los permisos que poseen sobre el mismo a) el dueño del archivo, b) el grupo
dueño, y c) el resto de los usuarios del sistema.

2. Esta columna nos dice si este objeto posee enlaces que lo estén apuntando.

3. Usuario dueño del objeto.


4. Grupo dueño del objeto.

5. Tamaño en bytes del objeto. Para mostrar este dato en una unidad más amigable
(KB, MB, etc.) podemos agregar la opción -h.

6. Fecha de última modificación del objeto.


Por ejemplo, el comando
ls -lh adm.txt

nos indica lo siguiente:

1. Se trata de un archivo propiamente dicho, ya que el primer caracter de la


secuencia -rw-r--r-- es -.

2. El archivo tiene un (1) enlace que apunta hacia el mismo.

3. El dueño del archivo es el usuario alumno.

4. El grupo dueño es finanzas.

5. El tamaño del archivo es 3,9 KB.


6. La última modificación fue realizada el día 2 de abril del corriente año a las
19:03.

Si dentro de un directorio existen subdirectorios y nos interesa ver el contenido de


todos simultáneamente, se puede utilizar la opción -R para mostrar de forma
recursiva tal información. Dicho de otra forma, ls -lR pruebas nos devolverá un
listado detallado de tal directorio y de todos los subdirectorios que se encuentren
dentro del mismo.

El comando mkdir (make directory)


Con este comando creamos nuevos directorios vacíos. En este ejemplo veremos cómo
hacerlo al crear un nuevo directorio llamado nuevodir:
mkdir nuevodir

Si deseamos crear una estructura completa de directorios (un subdirectorio dentro de


otro, y este último dentro de otro, y así sucesivamente) deberemos utilizar la opción -
p de la siguiente manera:
mkdir -p dir1/dir2/dir3
El comando anterior creará dir1 dentro del directorio actual. Si miramos dentro de
dir1 encontraremos a dir2, y dentro de este último a dir3:

El comando rmdir (remove directory)


El comando rmdir permite borrar directorios, si los mismos están vacíos. También
podemos utilizar la opción -p (de forma similar a como lo hicimos con mkdir) para
eliminar una estructura de directorios que cumplan con la misma condición.
Si los directorios contienen archivos, tendremos que utilizar el comando rm para
borrarlos previamente como veremos más adelante.

El comando cp (copy)
La herramienta cp se usa para copiar archivos. A continuación del comando
propiamente dicho, se debe escribir el archivo que se desee copiar y el destino donde
se habrá de guardar la copia.

Una opción interesante de este comando es -a, la cual hace una copia
exacta de los directorios y subdirectorios. Esto también incluye los
permisos o links que pudiera haber en el directorio de origen.

Por ejemplo:
cp pruebas/holamundo.txt .

copiará el archivo holamundo.txt, ubicado dentro del directorio pruebas, en el


directorio actual (representado por .) con el mismo nombre.
Por otro lado,
cp pruebas/ejemplo.txt copiaejemplo.txt

hará una copia del archivo ejemplo.txt que se halla dentro de pruebas, en el
directorio actual, pero con el nombre copiaejemplo.txt.
Veamos el resultado de los dos comandos anteriores:

Es importante tener en cuenta que si el archivo de destino existe, se sobreescribirá


mediante el proceso de copia.

El comando mv (move)
Esta herramienta se utiliza tanto para mover archivos de un lugar a otro como
también para renombrarlos. Es importante tener en cuenta que si el archivo de destino
existe, se sobreescribirá mediante este proceso.
Para ilustrar, cambiemos el nombre de copiaejemplo.txt a nuevacopiaejemplo.txt.
Luego de ejecutar el comando
mv copiaejemplo.txt nuevacopiaejemplo.txt

el primer archivo no existe más.


A continuación, movamos holamundo.txt desde el directorio actual a archivo3:
mv holamundo.txt archivo3

En la imagen siguiente vemos el resultado de los comandos anteriores:

Vemos que holamundo.txt ya no se encuentra en el directorio actual pero sí dentro


del directorio archivo3.
El comando rm (remove)
Este comando se utiliza para borrar archivos. Debemos tener en cuenta que desde la
línea de comandos no tenemos papelera de reciclaje, y tampoco hay un undelete, así
que cuando borramos nunca más podemos recuperar el archivo original. Para
remover un directorio junto con todo su contenido empleamos la opción -r, con
sumo cuidado por la misma razón señalada antes.
Debido a que no podemos recuperar archivos borrados con rm, es una buena idea
utilizar este comando siempre con la opción -i, lo que nos pedirá confirmación antes
de efectuar la operación. Dicho de otra forma:
rm -ri midirectorio

es una opción más adecuada que


rm -r midirectorio

para evitar el borrado accidental de los contenidos de midirectorio.

Buscar con find


Son muchas las razones por las que nos interesaría buscar archivos dentro de nuestro
sistema, entre las cuales podríamos mencionar las siguientes. Vamos a necesitar
realizar una búsqueda de archivos con find cuando querramos:
1. trabajar con un archivo que no sabemos o no recordamos dónde se encuentra.

2. identificar archivos

• por propietario o grupo dueño.

• por fecha de modificación

• por permisos asignados

• por tipo de archivo (archivo regular, directorio, etc)

• combinando los criterios anteriores


La sintaxis de find para comenzar una búsqueda en el directorio especificado por
RUTA es la siguiente:
find [RUTA] [OPCIONES]

Para buscar un archivo por nombre, utilizamos find seguido del directorio a partir del
cual deseamos realizar la búsqueda, de la opción -name (o -iname si deseamos ignorar
mayúsculas y minúsculas), y finalmente el nombre del archivo.
Si utilizamos un comodín (*) en el nombre del archivo como criterio de búsqueda,
deberemos encerrar el mismo entre comillas para evitar que la shell lo expanda (lo
cual sucedería ANTES de efectuar la búsqueda propiamente dicha).
Veamos los siguientes ejemplos:
• Buscar en el directorio /etc todos los archivos con extensión .conf: find /etc -
name '*.conf'

• Buscar los archivos cuyo tamaño esté entre 10 MB y 20 MB: find / -size
+10240k -size -20480k

• Buscar todos los archivos con find dentro del directorio /etc cuyo dueño sea el
usuario root y que fueron modificados exactamente hace 2 meses (60 días): find
/etc -type f -user root -mtime 60

Si quisiéramos ver la misma lista de archivos que fueron modificados hace más de un
cierto número de días, deberemos usar dicha cantidad con el signo + delante. En
resumen:
• -mtime x: archivos modificados exactamente hace x por 24 horas (lo cual se
traduce en x cantidad de días).

• -mtime -x: modificados durante los últimos x días.

• -mtime +x: modificados hace más de x días.

• Especificar un permiso particular como criterio de búsqueda a través de la opción


-perm a partir del directorio raíz: find / -type f -perm 777

• Encontrar archivos ejecutables por todos en el directorio actual: find . -type f


-perm -o=x

• Buscar archivos vacíos a partir del directorio raíz: find / -type f -empty

Para ejecutar una acción determinada sobre los resultados de una búsqueda
emplearemos la opción -exec. Por ejemplo, para cambiar los permisos de 777 a 644,
utilizaremos -exec seguida de la acción que deseamos realizar (en este caso chmod
644 a todos los archivos resultantes, simbolizados por {}+:
find . -type f -perm 777 -exec chmod 644 {} +

Para borrar archivos usaremos la opción -delete de GNU find (en este caso no es
necesario recurrir a -exec para especificar la acción deseada ya que la misma es
provista por una opción en particular). Veamos cómo borrar archivos vacíos:
find . -type f -empty -delete
La diferencia entre find y locate (otra herramienta utilizada para realizar
búsquedas) es que el primero emplea la estructura del sistema de archivos (o una
porción de esta) para realizar una búsqueda, mientras que locate lee la ubicación de
los archivos desde una base de datos interna.

Mostrar salida de un comando por pantalla y guardar el resultado al mismo


tiempo
Cuando queremos guardar la salida de un comando en un archivo utilizamos el
operador de redirección simple >. Si deseamos agregar más contenido posteriormente
usamos el operador de redirección doble >>. En el caso de que queramos enviar la
salida de un comando como entrada a otro empleamos el operador tubería |. ¿Pero
qué sucede cuando deseamos ver la salida de un comando por pantalla y guardar el
resultado en un archivo? Para lograrlo podemos utilizar una herramienta llamada tee.
Consideremos el siguiente ejemplo. Como sabemos, el comando
ls -l

nos mostrará un listado detallado de los contenidos del directorio actual. Esto incluye
permisos, dueño, grupo propietario, y fecha de última modificación de cada ítem,
entre otros datos. Al complementar este comando con una tubería y enviando la salida
hacia tee lograremos nuestro objetivo. La salida será mostrada por pantalla y será
guardada en el archivo listado.txt:
ls -l | tee listado.txt

Ahora examinemos el comando


wget -O- http://mirror.rackspace.com/CentOS/7/isos/x86_64/CentOS-7-x86_64
-Minimal-1804.iso | tee centos7.iso | sha256sum > dvd.sha256

Si acertamos al afirmar que nos permite descargar una imagen ISO de CentOS 7,
guardarla en el archivo centos7.iso y al mismo tiempo calcular su hash sha256 (y
guardarla en dvd.sha256) para verificar su integridad, ¡estamos en lo correcto! Como
podemos ver, la combinación de las redirecciones, tuberías, y el comando tee nos
permite realizar las más variadas tareas.
Otro punto importante a tener en cuenta cuando hablamos de redirecciones es la
necesidad de ejecutar un comando sobre todos los resultados de otro. Para esto
usamos la herramienta xargs.
Consideremos el siguiente ejemplo para ilustrar. Con el comando find localizamos
todos los archivos con la extensión .txt y mostramos su ubicación. Al enviar la salida a
xargs podemos especificar que se realice una acción diferente sobre cada línea del
resultado (ls -l en este caso):
find . -maxdepth 1 -type f -name "*.txt"
find . -maxdepth 1 -type f -name "*.txt" | xargs ls -l

Veamos el resultado:

En síntesis, podremos utilizar xargs cada vez que necesitemos operar sobre los
resultados de una búsqueda con find (que es lo más usual) o de algún otro comando.

Archivado y compresión
En Linux, el archivado y compresión se realiza utilizando el comando tar (archivado)
en conjunto con gzip, bzip2, o xz (compresión). La posibilidad de disponer de un solo
archivo comprimido (a menudo llamado tarball) que contenga muchos otros
(incluyendo directorios) nos permite distribuirlo fácilmente mediante correo
electrónico o transferirlo a través de una red, con la ventaja adicional de que su
tamaño es menor que la suma de sus contenidos.
A modo informativo, las nuevas versiones del kernel se distribuyen
desde kernel.org comprimidas con xz.

Si bien es perfectamente posible archivar un grupo de archivos y directorios SIN


comprimirlos, esta opción rara vez se utiliza, ya que siempre es preferible disponer de
un archivo final de menor tamaño. Por ese motivo, nos enfocaremos exclusivamente
en ambas operaciones (archivado y compresión).
Antes de comenzar, necesitaremos crear unos archivos de prueba y un subdirectorio
en el directorio actual:
echo "Yo soy el archivo1" > archivo1.txt
echo "Yo soy el archivo2 y peso más que archivo1" > archivo2.txt
echo "Yo soy el archivo3 y penso más que archivo1 y que archivo2" > archi
vo3.txt
mkdir resultados

A continuación, veamos cómo comprimir este grupo de archivos con cada una de las
herramientas que mencionamos hace instantes:
• Para comprimir y empaquetar archivo1.txt, archivo2.txt, y archivo3.txt con
gzip y tar en un archivo de nombre tarcongzip.tar.gz dentro del subdirectorio
resultados debemos hacer lo siguiente:
tar -czvf resultados/tarcongzip.tar.gz archivo1.txt archivo2.txt
archivo3.txt

• Con tar y bzip2:


tar -cjvf resultados/tarconbzip2.tar.bz2 archivo1.txt archivo2.txt
archivo3.txt

• Finalmente, con tar y xz:


tar -cJvf resultados/tarconxz.tar.xz archivo1.txt archivo2.txt
archivo3.txt

Como observamos en los ejemplos, los comandos en cada caso son prácticamente
idénticos. La única diferencia reside en el uso de las opciones -z, -j, y -J que
representan la compresión con gzip, bzip2, y xz respectivamente.
Antes de descomprimir, crearemos tres directorios auxiliares dentro de resultados:
mkdir resultados/1
mkdir resultados/2
mkdir resultados/3
Y luego descomprimiremos los contenidos en tarcongzip.tar.gz,
tarconbzip2.tar.bz2, y tarconxz.tar.xz en resultados/1, resultados/2, y
resultados/3. La opción -C (mayúscula) nos permite indicar un directorio destino
para los archivos descomprimidos antes de realizar la operación propiamente dicha:
tar -xzvf resultados/tarcongzip.tar.gz -C resultados/1
tar -xjvf resultados/tarconbzip2.tar.bz2 -C resultados/2
tar -xJvf resultados/tarconxz.tar.xz -C resultados/3

Resaltemos algunos puntos importantes a tener en cuenta en todos los casos:


• La opción -c indica que estamos creando un tarball, mientras que -x nos dice que
lo estamos descomprimiendo.
• -v muestra la lista de archivos que fueron procesados.

• -f es la última opción y debe preceder al nombre del tarball a crear.

• gzip es la herramienta más antigua de las tres y provee la menor compresión,


mientras que xz es la más nueva y presenta una mayor compresión, pero a costa
de un mayor uso de recursos del sistema al momento de comprimir. Finalmente,
bzip2 es una especie de promedio entre las otras dos.

• Cabe destacar que todas las opciones de tar (que podemos consultar en el man
page correspondiente) se pueden utilizar con cualquiera de las herramientas de
compresión mencionadas anteriormente.

Si bien existen otras herramientas más potentes y versátiles (aunque complejas) para
realizar copias de respaldo en Linux, todo administrador de sistemas debe conocer
tar y las herramientas de compresión como la palma de su mano.

También podría gustarte