Curso de Terminal y Bash
Aprende a dominar la línea de comandos desde cero. Un curso práctico y progresivo que te llevará desde los conceptos básicos hasta la automatización con scripts.
Este curso es parte de los módulos previos al curso de Ciencia de Datos en Salud de Hazla con Datos y es complementario al curso de configuración del entorno de desarrollo. No necesitas experiencia previa: si puedes usar un navegador web, puedes aprender la terminal.
El timer Pomodoro te ayuda a estudiar en bloques cortos de concentración (25 min) con descansos. Está demostrado que mejora el aprendizaje y reduce la fatiga mental.
Requisito previo: Configuración del entorno
Antes de comenzar, necesitas tener una terminal funcionando. Este curso te guía paso a paso según tu sistema operativo (Windows con WSL, macOS o Linux).
Ir al curso de configuración →Introducción
¿Qué es la terminal?
Cuando usas tu computador normalmente, haces clic en iconos, arrastras archivos y navegas por menús visuales. Eso se llama interfaz gráfica (o GUI). La terminal es una forma diferente de interactuar con tu computador: en lugar de hacer clic, escribes instrucciones en texto. Puede parecer intimidante al principio, pero una vez que le tomas el ritmo, muchas tareas se vuelven más rápidas y poderosas.
Piensa en la terminal como una conversación directa con tu computador. Tú escribes un comando, presionas Enter, y el computador te responde con el resultado. Así de simple.
¿Por qué es importante para ciencia de datos?
Este curso es parte de los módulos previos al curso de Ciencia de Datos en Salud de Hazla con Datos y está pensado como un complemento directo del curso de configuración del entorno de desarrollo. Si estás aprendiendo ciencia de datos, la terminal va a aparecer constantemente en tu camino:
- Instalar herramientas: Python, R, librerías, gestores de paquetes… todo se instala más fácil por terminal.
- Usar Git: El control de versiones, fundamental para cualquier proyecto de datos, funciona desde la terminal.
- Trabajar con servidores: Si necesitas procesar datos en la nube o en un servidor remoto, la terminal es tu única opción.
- Automatizar tareas: ¿Descargar datos todos los días? ¿Limpiar archivos temporales? Los scripts de Bash lo hacen por ti.
- Docker y contenedores: Herramientas modernas de ciencia de datos se manejan desde la línea de comandos.
No necesitas ser experto en terminal para hacer ciencia de datos, pero sí necesitas sentirte cómodo con lo básico. Este curso te lleva exactamente hasta ese punto.
Conceptos clave que debes conocer
Antes de empezar, hay algunos términos que vas a escuchar mucho. No te preocupes por memorizarlos ahora; los irás entendiendo con la práctica.
La terminal es la aplicación o ventana donde escribes comandos. En Windows puedes usar Windows Terminal con WSL, en macOS está la app Terminal, y en Linux hay varias opciones como GNOME Terminal o Konsole.
El shell es el programa que interpreta lo que escribes y lo convierte en instrucciones que el computador entiende. Es como un traductor entre tú y el sistema operativo. Los shells más comunes son:
- Bash (“Bourne Again Shell”): el shell estándar en la mayoría de distribuciones Linux. Es el que usaremos en este curso.
- Zsh (“Z Shell”): un shell más moderno que viene por defecto en macOS desde Catalina. Tiene mejor autocompletado y personalización.
La buena noticia es que Bash y Zsh son muy similares para uso básico. Todo lo que aprenderás en este curso funciona igual en ambos. Las diferencias importantes solo aparecen en configuraciones avanzadas que no cubrimos aquí.
El prompt es el texto que aparece antes de tu cursor, esperando que escribas algo. Generalmente muestra tu nombre de usuario, el nombre del computador y el directorio donde estás. Se ve algo así:
usuario@mi-pc:~$Cuando veas el $ al final, significa que la terminal está lista para recibir tu comando.
Configuración del entorno
Requisito previo: Configuración del entorno
Antes de continuar, necesitas tener una terminal funcionando en tu computador. Si aún no la tienes lista, sigue el curso de configuración del entorno donde te guiamos paso a paso según tu sistema operativo (Windows con WSL, macOS o Linux).
Ir al curso de configuración →
Tu primer comando
Una vez que tengas tu terminal abierta, vamos a verificar que todo funciona. Escribe exactamente esto y presiona Enter:
echo "¡Hola, terminal!"Si ves el mensaje ¡Hola, terminal! en la pantalla, felicidades: tu terminal está funcionando correctamente y acabas de ejecutar tu primer comando. El comando echo simplemente repite lo que le escribas. Parece básico, pero lo usarás mucho más adelante.
No te preocupes por los errores
Si escribes algo mal, la terminal te mostrará un mensaje de error. No pasa nada grave: simplemente lee el mensaje, corrige el comando y vuelve a intentar. La terminal no va a “romperse” porque te equivoques en un comando.
Ejercicios del módulo
Antes de pasar al siguiente módulo, practica lo siguiente:
- Abre tu terminal y escribe
echoseguido de tu nombre. ¿Qué aparece? - Escribe un comando cualquiera inventado (como
hola). Lee el mensaje de error que aparece. ¿Qué te dice? - Presiona la flecha arriba en tu teclado. ¿Qué pasa? Esto te será muy útil más adelante.
- Escribe
datey presiona Enter. ¿Qué información te muestra?
Primeros pasos y navegación
Tus primeros comandos
Ahora que ya sabes abrir la terminal y ejecutar un comando, vamos a conocer algunos comandos básicos que te ayudarán a orientarte. Piensa en estos como las primeras palabras que aprendes en un idioma nuevo.
El comando echo ya lo conoces: repite lo que le escribas. Pero hay otros igual de sencillos:
echo "Hola mundo" # Imprime texto en pantallawhoami # Muestra tu nombre de usuariodate # Muestra la fecha y hora actualcal # Muestra el calendario del mesclear # Limpia la pantalla (o Ctrl+L)Prueba cada uno de estos comandos en tu terminal. No necesitas memorizarlos, solo familiarízate con la idea de que cada comando tiene un nombre corto y hace una tarea específica. Con el tiempo los irás recordando de forma natural.
Atajo útil
Puedes usar Ctrl + L para limpiar la pantalla rápidamente, en lugar de escribir clear. Este atajo funciona en casi todas las terminales y lo usarás todo el tiempo.
El sistema de archivos: cómo se organiza todo
Antes de aprender a moverte por el sistema, necesitas entender cómo está organizado. En tu computador, los archivos están guardados dentro de carpetas (también llamadas directorios), y esas carpetas pueden contener otras carpetas, formando una estructura como un árbol invertido.
En Linux y macOS, todo parte de un directorio raíz llamado / (una barra diagonal). Desde ahí se ramifica todo lo demás:
/├── home/ # Aquí viven los directorios de cada usuario│ └── tu-usuario/│ ├── Documentos/│ ├── Descargas/│ └── ...├── etc/ # Archivos de configuración del sistema├── var/ # Datos variables (logs, bases de datos)├── tmp/ # Archivos temporales└── usr/ # Programas instaladosLo más importante para ti ahora es la carpeta home (representada por ~). Es tu espacio personal dentro del sistema. Cuando abres la terminal, normalmente empiezas ahí. Es como tu escritorio, pero en la terminal.
Saber dónde estás: pwd
Cuando navegas por carpetas en la interfaz gráfica, puedes ver en qué carpeta estás mirando la barra de direcciones. En la terminal, usas el comando pwd (que significa “print working directory”, o “imprime el directorio de trabajo”):
pwdEste comando es tu brújula. Cada vez que te sientas perdido, escribe pwd y sabrás exactamente dónde estás.
Ver qué hay alrededor: ls
Una vez que sabes dónde estás, querrás ver qué archivos y carpetas hay en ese lugar. Para eso usas ls (de “list”):
# Ver qué hay en el directorio actualls
# Ver con más detalle (permisos, tamaño, fecha)ls -l
# Incluir archivos ocultos (los que empiezan con un punto)ls -la
# Tamaños en formato legible (KB, MB, GB en vez de bytes)ls -lh¿Qué son los archivos ocultos? En Linux, cualquier archivo o carpeta cuyo nombre empiece con un punto (.) está oculto por defecto. Estos suelen ser archivos de configuración. Por ejemplo, .bashrc es el archivo de configuración de Bash. El flag -a le dice a ls que los muestre también.
¿Qué son los flags?
Los flags (o banderas) son opciones que modifican el comportamiento de un comando. Se escriben con un guión antes de una letra: -l, -a, -h. Puedes combinarlos: ls -la es lo mismo que ls -l -a. Cada comando tiene sus propios flags; no necesitas aprenderlos todos, solo los más útiles.
Moverse entre carpetas: cd
Para entrar a una carpeta, usas cd (de “change directory”). Para salir, usas cd .. (los dos puntos significan “el directorio de arriba”):
| Comando | Descripción |
|---|---|
| cd carpeta | Entra a un directorio |
| cd .. | Sube un nivel (al directorio padre) |
| cd ~ | Ir al directorio home, sin importar dónde estés |
| cd - | Volver al directorio donde estabas antes |
| cd / | Ir al directorio raíz del sistema |
Vamos a practicar la navegación paso a paso:
# Primero, veamos dónde estamospwd# ¿Qué hay aquí?ls# Documentos Descargas Escritorio Imágenes
# Entremos a Documentoscd Documentos
# Verificamos que nos movimospwd# /home/tu-usuario/Documentos
# Subimos un nivel (volvemos a home)cd ..
# Verificamospwd# /home/tu-usuario
# Vamos directo al home desde cualquier lugarcd ~Rutas absolutas vs relativas
Hay dos formas de decirle a la terminal a qué carpeta quieres ir. Entender la diferencia es importante porque la usarás en todo momento.
Una ruta absoluta empieza siempre desde la raíz /. Es como dar una dirección completa: “Chile, Santiago, calle X, número Y”. No importa dónde estés, la ruta absoluta siempre te lleva al mismo lugar:
cd /home/usuario/Documentos/proyectoUna ruta relativa empieza desde donde tú estás ahora. Es como decir “la tienda de la esquina”: depende de dónde te encuentres en ese momento:
# Si estás en /home/usuario, esto te lleva a /home/usuario/Documentos/proyectocd Documentos/proyecto
# Los dos puntos (..) significan "sube un nivel"cd ../otro-proyecto¿Cuándo usar cada una?
Usa rutas relativas para moverte entre carpetas cercanas (es más corto de escribir). Usa rutas absolutas cuando quieras ir a un lugar específico sin importar dónde estés, o dentro de scripts para evitar errores.
Símbolos especiales de ruta
Estos símbolos los usarás constantemente. Vale la pena entenderlos bien:
| Símbolo | Significado | Ejemplo |
|---|---|---|
. | El directorio donde estás ahora | ./script.sh (ejecutar algo aquí) |
.. | El directorio de arriba (padre) | cd .. (subir un nivel) |
~ | Tu directorio home | cd ~ (ir a casa) |
/ | La raíz del sistema (el punto más alto) | cd / |
- | El directorio anterior (solo con cd) | cd - (ir y volver) |
Autocompletado con Tab: tu mejor herramienta
Si hay un truco que debes aprender de este curso, es este: la tecla Tab autocompleta nombres. No necesitas escribir nombres completos de archivos o carpetas. Escribe las primeras letras y presiona Tab; la terminal completa el resto por ti.
# Escribe "cd Doc" y presiona Tabcd Doc⇥ # Se completa a: cd Documentos/
# Si hay varias opciones que empiezan igual, presiona Tab dos veces# y la terminal te muestra todas las posibilidadescd D⇥⇥# Descargas/ Documentos/ Desktop/Esto no solo te ahorra tiempo: evita errores de escritura. Si Tab no completa nada, probablemente el archivo o carpeta no existe, o escribiste mal las primeras letras.
Usa Tab obsesivamente
Los usuarios experimentados de terminal presionan Tab después de cada 2-3 letras. Es un hábito que deberías adoptar desde ahora. Te ahorrará cientos de errores y mucho tiempo.
Historial de comandos
La terminal recuerda todos los comandos que has escrito. Esto es increíblemente útil porque rara vez necesitas escribir un comando desde cero:
- Flecha arriba: Muestra el comando anterior. Sigue presionando para ir más atrás.
- Flecha abajo: Vuelve hacia comandos más recientes.
history: Muestra el historial completo de comandos.Ctrl + R: Busca un comando en el historial. Escribes parte del comando y te encuentra la coincidencia.!!: Repite exactamente el último comando.
# Ver los últimos 10 comandos que ejecutastehistory | tail -10
# Buscar un comando que usaste antes# Presiona Ctrl+R, escribe parte del comando (ej: "git") y apareceráCtrl+R es mágico
Imagina que hace una hora escribiste un comando largo y complicado. En lugar de recordarlo letra por letra, presionas Ctrl + R, escribes unas pocas letras que recuerdas, y la terminal lo encuentra por ti. Es uno de los atajos más útiles que existen.
Ejercicios del módulo
Practica cada uno de estos ejercicios en tu terminal:
- Ejecuta
whoami,dateycaluno por uno. ¿Qué te muestra cada uno? - Usa
pwdpara ver dónde estás. Luego usalspara ver qué hay en tu directorio home. - Usa
ls -lay compara conls. ¿Qué archivos nuevos aparecen? (Pista: busca los que empiezan con punto) - Navega a una carpeta cualquiera con
cd, luego usapwdpara confirmar dónde estás. Vuelve al home concd ~. - Practica el autocompletado: escribe
cdseguido de las primeras 2 letras de una carpeta y presiona Tab. ¿Se completó? - Ejecuta
historyy mira los comandos que has escrito en esta sesión. Luego presionaCtrl + Ry busca el comandodate. - Navega a
/tmpcon ruta absoluta, luego vuelve a tu home concd ~. Ahora usacd -. ¿A dónde te lleva?
Archivos y directorios
Ahora que sabes moverte por el sistema de archivos, es momento de aprender a crear, copiar, mover y eliminar archivos y carpetas. Estos son los comandos que más usarás en el día a día.
Crear directorios con mkdir
El comando mkdir (de “make directory”) crea una carpeta nueva. Es equivalente a hacer clic derecho y seleccionar “Nueva carpeta” en la interfaz gráfica, pero más rápido:
# Crear una carpetamkdir mi-proyecto
# Crear varias carpetas a la vezmkdir css js img¿Y si necesitas crear una carpeta dentro de otra que tampoco existe? Por ejemplo, quieres crear proyecto/src/components pero ni proyecto ni src existen todavía. Si intentas hacerlo directamente, obtendrás un error. Para eso existe el flag -p, que crea toda la estructura de carpetas intermedias:
# Sin -p, esto daría error si "proyecto" no existemkdir -p proyecto/src/components
# Crea "proyecto", luego "src" dentro, luego "components" dentroConsejo práctico
Acostúmbrate a usar mkdir -p siempre. Si las carpetas ya existen, no pasa nada (no da error). Si no existen, las crea. Es más seguro.
Crear archivos con touch
El comando touch crea un archivo vacío. Su nombre viene de “tocar” el archivo; si el archivo ya existe, simplemente actualiza su fecha de modificación sin cambiar el contenido:
# Crear un archivo vacíotouch archivo.txt
# Crear varios archivos de una veztouch index.html style.css app.js
# Si el archivo ya existe, solo actualiza la fecha (no borra nada)touch archivo-existente.txtEn la práctica, touch es la forma más rápida de crear un archivo vacío que luego vas a editar.
Copiar archivos y directorios con cp
El comando cp (de “copy”) copia archivos. Funciona con la lógica de cp origen destino:
# Copiar un archivocp archivo.txt copia.txt
# Copiar un archivo a otra carpetacp archivo.txt carpeta/
# Copiar un archivo a otra carpeta con otro nombrecp archivo.txt carpeta/nuevo-nombre.txtPara copiar una carpeta completa con todo su contenido, necesitas el flag -r (de “recursivo”). Sin este flag, cp solo copia archivos sueltos:
# Esto NO funciona sin -r (da error)cp mi-carpeta/ copia-carpeta/
# Esto SÍ funciona: copia la carpeta y todo lo de dentrocp -r mi-carpeta/ copia-carpeta/¿Qué significa recursivo?
“Recursivo” significa que el comando se aplica a la carpeta y a todo lo que hay dentro: subcarpetas, archivos dentro de subcarpetas, etc. Verás el flag -r en varios comandos. Siempre significa lo mismo: “incluye todo lo de adentro”.
Un ejemplo práctico muy común es hacer un respaldo antes de modificar algo:
# Antes de hacer cambios importantes, haz una copiacp -r mi-proyecto/ mi-proyecto-respaldo/Mover y renombrar con mv
El comando mv (de “move”) hace dos cosas: mover archivos a otra ubicación y renombrar archivos. En la terminal, mover y renombrar son la misma operación:
# Renombrar un archivo (misma carpeta, otro nombre)mv nombre-viejo.txt nombre-nuevo.txt
# Mover un archivo a otra carpeta (no cambia el nombre)mv archivo.txt carpeta/
# Mover Y renombrar al mismo tiempomv viejo.txt carpeta/nuevo.txt
# Mover una carpeta completa (no necesita -r como cp)mv proyecto/ /home/usuario/Documentos/A diferencia de cp, el comando mv no necesita -r para mover carpetas. Simplemente las mueve completas.
mv no hace copia
Recuerda que mv mueve el archivo: desaparece del lugar original. Si quieres mantener el original y crear una copia en otro lugar, usa cp en su lugar.
Eliminar archivos y directorios con rm
Aquí necesitamos ir con mucho cuidado. El comando rm (de “remove”) elimina archivos permanentemente. No hay papelera de reciclaje, no hay “deshacer”, no hay manera de recuperar lo que borres. Una vez que presionas Enter, el archivo desaparece para siempre.
rm es permanente e irreversible
A diferencia de la papelera de reciclaje de tu escritorio, rm elimina archivos de forma definitiva. Antes de ejecutar cualquier rm, lee dos veces lo que vas a borrar. Una buena práctica es usar ls primero con el mismo patrón para verificar qué archivos coinciden.
# Eliminar un archivorm archivo.txt
# Eliminar con confirmación (te pregunta antes de borrar cada archivo)rm -i archivo.txt# rm: ¿borrar el fichero regular 'archivo.txt'? (s/n)Para eliminar carpetas, necesitas decidir si están vacías o no:
# Eliminar una carpeta vacía (solo funciona si no tiene nada dentro)rmdir carpeta-vacia
# Eliminar una carpeta CON contenido (recursivo)rm -r carpeta/PELIGRO: comandos que nunca debes ejecutar
Existen combinaciones de rm que pueden destruir tu sistema completo. Nunca ejecutes estos comandos:
rm -rf /— Borra TODO el sistema operativo.rm -rf *— Borra todo el contenido del directorio actual.rm -rf ~— Borra todo tu directorio home (tus documentos, configuraciones, todo).
El flag -f (force) omite confirmaciones y el flag -r (recursive) borra todo lo de adentro. Juntos son extremadamente peligrosos si se aplican al lugar equivocado.
Una forma más segura de trabajar con rm es usar siempre el flag -i para que te pida confirmación, o verificar antes con ls:
# Primero verifica qué archivos vas a borrarls *.tmp# archivo1.tmp archivo2.tmp resultado.tmp
# Si estás seguro, borrarm *.tmp
# O usa -i para que te pregunte uno por unorm -i *.tmpWildcards (comodines): seleccionar varios archivos a la vez
Los comodines son patrones que te permiten referirte a múltiples archivos sin escribir cada nombre. Son muy útiles combinados con cp, mv, rm y ls:
El comodín más usado es * (asterisco), que significa “cualquier cantidad de cualquier carácter”:
# Todos los archivos que terminan en .txtls *.txt
# Todos los archivos que empiezan con "datos"ls datos*
# Todos los archivos (cualquier nombre, cualquier extensión)ls *Otros comodines útiles:
| Wildcard | Significado | Ejemplo |
|---|---|---|
* | Cualquier cantidad de caracteres | *.txt = todos los .txt |
? | Exactamente un carácter | archivo?.txt = archivo1.txt, archivoA.txt |
[abc] | Uno de los caracteres listados | archivo[123].txt = archivo1, archivo2, archivo3 |
[a-z] | Un carácter en el rango | [A-Z]*.txt = archivos que empiezan con mayúscula |
# Copiar todas las imágenes a una carpetacp *.jpg imagenes/cp *.png imagenes/
# Mover todos los archivos de datosmv datos_*.csv carpeta-datos/
# Listar archivos que empiezan con "test"ls test*Cuidado con rm y wildcards
Antes de ejecutar rm *.algo, siempre ejecuta ls *.algo primero para ver qué archivos coinciden. Un wildcard mal escrito puede borrar archivos que no esperabas. Por ejemplo, rm * .txt (con un espacio antes del punto) borraría TODOS los archivos y luego intentaría borrar un archivo llamado .txt.
Visualizar la estructura con tree
El comando tree te muestra la estructura de carpetas de forma visual, como un árbol. Es excelente para entender cómo está organizado un proyecto:
# Instalar tree (no viene preinstalado)sudo apt install tree # Debian/Ubuntu/WSLbrew install tree # macOS
# Ver la estructura completatree
# Limitar la profundidad (2 niveles)tree -L 2
# Ver solo directorios (sin archivos)tree -d.├── src/│ ├── index.html│ ├── css/│ │ └── style.css│ └── js/│ └── app.js├── package.json└── README.mdEncontrar archivos con find
Cuando tienes muchos archivos y carpetas, find te ayuda a buscar archivos por nombre, tipo, tamaño o fecha de modificación:
# Buscar todos los archivos .txt desde el directorio actualfind . -name "*.txt"
# Buscar solo directorios con un nombre específicofind . -type d -name "src"
# Buscar archivos modificados en las últimas 24 horasfind . -mtime -1
# Buscar archivos mayores a 10MBfind . -size +10MEl punto . al inicio significa “buscar desde aquí”. Podrías reemplazarlo por cualquier ruta, como /home/usuario o /var/log.
Resumen de comandos
| Comando | Descripción |
|---|---|
| mkdir carpeta | Crear directorio |
| mkdir -p a/b/c | Crear directorios anidados |
| touch archivo | Crear archivo vacío |
| cp origen destino | Copiar archivo |
| cp -r carpeta/ copia/ | Copiar directorio completo |
| mv origen destino | Mover o renombrar |
| rm archivo | Eliminar archivo (permanente) |
| rm -i archivo | Eliminar con confirmación |
| rm -r carpeta/ | Eliminar directorio y todo su contenido |
| rmdir carpeta | Eliminar directorio vacío |
| tree | Ver estructura de directorios visualmente |
| find . -name patrón | Buscar archivos por nombre |
Ejercicios del módulo
- Crea una carpeta llamada
practicaen tu home. Dentro de ella, crea tres subcarpetas:datos,scriptsyresultados. - Usando un solo comando con
mkdir -p, crea la estructuraproyecto/src/utils. - Dentro de
practica, crea 3 archivos vacíos:nota1.txt,nota2.txtynota3.txt. - Copia
nota1.txtadatos/con el nombrecopia-nota.txt. - Renombra
nota3.txtanota-final.txtusandomv. - Usa
ls *.txtdentro depracticapara ver todos los archivos .txt. ¿Cuántos aparecen? - Elimina
nota2.txtusandorm -i(con confirmación). Responde “s” cuando te pregunte. - Usa
tree practicapara ver la estructura completa que creaste. ¿Se ve como esperabas? - Usa
find practica -name "*.txt"para encontrar todos los .txt dentro de la carpeta. ¿Encuentra también el que copiaste adatos/? - Desafío: Elimina toda la carpeta
practicacon un solo comando. (Pista: necesitarás-r)
Visualización, búsqueda y redirecciones
En el módulo anterior aprendiste a crear y mover archivos. Ahora vas a aprender a ver lo que hay dentro de esos archivos, a buscar texto específico y a conectar comandos entre sí. Estas habilidades son las que realmente hacen poderosa a la terminal.
Ver el contenido de un archivo: cat
El comando más simple para ver el contenido de un archivo es cat (de “concatenate”). Muestra todo el contenido de una vez en la pantalla:
cat notas.txtcat funciona bien para archivos cortos. Pero si el archivo tiene cientos o miles de líneas, el texto pasará tan rápido que no podrás leerlo. Para esos casos, hay mejores opciones.
Navegar archivos largos: less
Cuando necesitas leer un archivo largo, less te permite navegar página por página, como un visor de documentos:
less archivo-largo.txtDentro de less, usas estas teclas para moverte:
| Tecla | Acción |
|---|---|
| Espacio | Avanzar una página |
| b | Retroceder una página |
| Flecha arriba/abajo | Mover línea por línea |
| /texto | Buscar “texto” hacia adelante |
| n | Ir a la siguiente coincidencia de búsqueda |
| q | Salir de less |
less es tu visor de archivos
Piensa en less como el equivalente a abrir un archivo con un visor de texto. Es perfecto para archivos de configuración, logs, o cualquier archivo que no necesitas editar, solo leer. Cuando termines de leer, presiona q para salir.
Ver solo el inicio o el final: head y tail
A veces no necesitas ver todo el archivo, solo las primeras o las últimas líneas. Para eso existen head y tail:
# Ver las primeras 10 líneas (por defecto)head archivo.txt
# Ver las primeras 20 líneashead -n 20 datos.csv
# Ver las últimas 10 líneastail archivo.txt
# Ver las últimas 5 líneastail -n 5 log.txttail tiene un truco especialmente útil: el flag -f (de “follow”) te permite monitorear un archivo en tiempo real. Cada vez que se agrega una nueva línea al archivo, aparece automáticamente en tu pantalla. Esto es invaluable para monitorear logs:
# Monitorear un archivo de log en tiempo realtail -f /var/log/syslog
# Presiona Ctrl+C para dejar de monitorearContar líneas, palabras y caracteres: wc
El comando wc (de “word count”) cuenta las líneas, palabras y caracteres de un archivo:
wc archivo.txt# 42 318 1847 archivo.txt# (42 líneas, 318 palabras, 1847 caracteres)
# Si solo te interesa la cantidad de líneaswc -l archivo.txt| Comando | Descripción |
|---|---|
| cat archivo | Muestra todo el contenido del archivo |
| less archivo | Visor paginado (navegar con flechas, salir con q) |
| head archivo | Muestra las primeras 10 líneas |
| head -n 20 archivo | Muestra las primeras 20 líneas |
| tail archivo | Muestra las últimas 10 líneas |
| tail -f archivo | Monitorea el archivo en tiempo real (Ctrl+C para salir) |
| wc archivo | Cuenta líneas, palabras y caracteres |
| wc -l archivo | Cuenta solo las líneas |
Buscar texto dentro de archivos: grep
grep es uno de los comandos más útiles que vas a aprender. Te permite buscar una palabra o patrón de texto dentro de uno o varios archivos. Su nombre viene de “Global Regular Expression Print”, pero no te preocupes por eso: piensa en grep como “buscar texto”.
La sintaxis básica es grep "lo que buscas" dónde buscas:
# Buscar la palabra "error" en un archivo de loggrep "error" log.txt
# La terminal mostrará todas las líneas que contengan "error"Ahora veamos las opciones más útiles de grep, una por una:
# Ignorar mayúsculas/minúsculas (-i)# Encuentra "Error", "ERROR", "error", etc.grep -i "error" log.txt
# Mostrar el número de línea donde aparece (-n)grep -n "error" log.txt# 23: [2024-01-15] error de conexión# 47: [2024-01-15] error de timeout
# Buscar en todos los archivos de una carpeta, recursivamente (-r)grep -r "TODO" ./src/
# Mostrar líneas que NO contienen el texto (-v)# Útil para filtrar: "todo excepto las líneas de debug"grep -v "debug" log.txt
# Contar cuántas veces aparece (-c)grep -c "error" log.txt# 15
# Solo mostrar los nombres de archivo que contienen el texto (-l)grep -rl "password" ./config/| Comando | Descripción |
|---|---|
| grep 'texto' archivo | Buscar texto en un archivo |
| grep -i | Buscar sin distinguir mayúsculas/minúsculas |
| grep -n | Mostrar números de línea |
| grep -r | Buscar en todos los archivos de una carpeta |
| grep -v | Mostrar líneas que NO contienen el texto |
| grep -c | Contar coincidencias |
| grep -l | Solo mostrar nombres de archivos con coincidencias |
grep y ciencia de datos
Si trabajas con archivos CSV o datos tabulares, grep te permite filtrar filas rápidamente. Por ejemplo, grep "Chile" datos.csv te muestra solo las filas que mencionan a Chile. No reemplaza a pandas o R, pero para revisiones rápidas es muy práctico.
Pipes (tuberías): conectar comandos con |
Aquí es donde la terminal se vuelve realmente poderosa. El pipe (representado por el símbolo |) toma la salida de un comando y la pasa como entrada al siguiente. Piensa en él como una tubería que conecta la salida de una herramienta con la entrada de otra.
Imagina que tienes una lista de 1000 archivos y quieres encontrar solo los que contienen “datos”. Sin pipes, tendrías que guardar la lista en un archivo, luego buscar en ese archivo. Con pipes, lo haces en una sola línea:
# Sin pipes (engorroso)ls > lista.txtgrep "datos" lista.txtrm lista.txt
# Con pipes (una sola línea)ls | grep "datos"Algunos ejemplos prácticos que usarás frecuentemente:
# Listar archivos y filtrar por nombrels -la | grep ".txt"
# Contar cuántos archivos hay en el directoriols | wc -l
# Ver procesos y buscar uno específicops aux | grep "python"
# Ver el historial y buscar un comandohistory | grep "git"
# Ordenar líneas de un archivo y eliminar duplicadoscat nombres.txt | sort | uniqFíjate cómo puedes encadenar varios pipes. Cada | pasa el resultado al siguiente comando. Es como una línea de ensamblaje: cada estación hace una tarea y pasa el resultado a la siguiente.
La filosofía Unix
La terminal está diseñada con una idea simple: cada comando hace UNA cosa bien. Los pipes permiten combinar estos comandos pequeños para resolver problemas complejos. Es como tener piezas de LEGO: cada pieza es simple, pero juntas puedes construir lo que quieras.
Redirecciones: guardar la salida en archivos
Los pipes conectan comandos entre sí. Las redirecciones envían la salida de un comando a un archivo en vez de mostrarla en pantalla. Hay dos tipos principales:
> (mayor que) envía la salida a un archivo. Si el archivo existe, lo sobreescribe (borra lo anterior):
# Guardar el listado de archivos en un archivols -la > listado.txt
# Guardar la fecha actualdate > fecha.txtCuidado con >
El operador > sobreescribe el archivo sin preguntar. Si ya tenías contenido importante en ese archivo, se perderá. Siempre verifica que no estés sobreescribiendo algo que necesitas.
>> (doble mayor que) agrega al final del archivo, sin borrar lo que ya tenía:
# Agregar una línea al finalecho "primera línea" > notas.txtecho "segunda línea" >> notas.txtecho "tercera línea" >> notas.txt
# Ahora notas.txt tiene las tres líneascat notas.txtTambién puedes redirigir los mensajes de error por separado:
| Operador | Función | Ejemplo |
|---|---|---|
> | Redirigir salida a archivo (sobreescribe) | echo "hola" > saludo.txt |
>> | Redirigir salida a archivo (añade al final) | echo "adiós" >> saludo.txt |
2> | Redirigir solo errores a archivo | comando 2> errores.log |
&> | Redirigir todo (salida + errores) a archivo | comando &> todo.log |
2>/dev/null | Descartar errores (no mostrarlos) | find / -name "*.conf" 2>/dev/null |
El último ejemplo es muy útil: /dev/null es un “agujero negro” donde puedes enviar lo que no te interesa. Si un comando produce muchos mensajes de error que no necesitas ver, los rediriges a /dev/null:
# find muestra errores de "permiso denegado" en muchas carpetas# Con 2>/dev/null solo vemos los resultados útilesfind / -name "*.conf" 2>/dev/nullCombinando todo: ejemplos del mundo real
Ahora que conoces pipes y redirecciones, veamos cómo se combinan para resolver problemas reales:
# Encontrar los 5 archivos más grandes del directoriodu -sh * | sort -rh | head -5
# Buscar errores recientes en un log y guardarlosgrep -i "error" /var/log/syslog | tail -20 > errores-recientes.txt
# Contar cuántas líneas tiene cada archivo .txtwc -l *.txt
# Ver las 10 palabras más frecuentes en un archivocat texto.txt | tr ' ' '\n' | sort | uniq -c | sort -rn | head -10No te preocupes si el último ejemplo parece complejo. El punto es que puedes construir soluciones paso a paso, agregando un pipe a la vez. Primero prueba el primer comando, luego agrega un pipe y el segundo, y así sucesivamente.
Ejercicios del módulo
- Crea un archivo con
echo "Línea 1" > prueba.txt, luego agrega “Línea 2” y “Línea 3” usando>>. Verifica concat prueba.txt. - Usa
head -n 1 prueba.txtytail -n 1 prueba.txt. ¿Qué línea muestra cada uno? - Usa
wc -l prueba.txtpara contar las líneas del archivo. ¿Coincide con lo que esperabas? - Ejecuta
ls /usr/bin | wc -lpara contar cuántos programas hay instalados en tu sistema. - Usa
ls /usr/bin | grep "python"para ver si tienes Python instalado. ¿Aparece algo? - Guarda el resultado de
ls -la ~en un archivo llamadomi-home.txtusando>. Luego abre el archivo conless mi-home.txt. - Ejecuta
history | grep "cd"para ver todos los comandoscdque has usado en esta sesión. - Crea un archivo con varias líneas:
echo -e "banana\nmanzana\nnaranja\nbanana\nmanzana" > frutas.txt. Luego usasort frutas.txt | uniqpara ver las frutas sin duplicados. - Usa
grep -c "banana" frutas.txtpara contar cuántas veces aparece “banana”. - Desafío: Usa
cat frutas.txt | sort | uniq -c | sort -rnpara ver cuál es la fruta más frecuente. ¿Qué hace cada parte del comando?
Editores de texto
Hasta ahora has aprendido a ver archivos con cat y less, pero ¿qué pasa cuando necesitas modificar un archivo directamente en la terminal? Para eso existen los editores de texto en terminal. Son esenciales cuando trabajas en servidores remotos (que no tienen interfaz gráfica) o cuando necesitas hacer una edición rápida sin abrir otro programa.
En este módulo aprenderás dos editores: Nano (fácil y amigable) y Vim (potente pero con curva de aprendizaje). Como principiante, te recomiendo empezar con Nano y aprender solo lo básico de Vim.
Nano: el editor amigable
Nano es el editor de texto más fácil de usar en la terminal. Si has usado un editor de texto gráfico como Notepad, Nano se sentirá familiar: escribes, borras, y usas atajos de teclado para guardar y salir.
Para abrir un archivo con Nano, simplemente escribe:
# Abrir un archivo existentenano archivo.txt
# Si el archivo no existe, Nano lo crea al guardarnano nuevo-archivo.txt
# Abrir con números de línea visibles (recomendado)nano -l archivo.txtCuando Nano se abra, verás el contenido del archivo en la pantalla y una barra de atajos en la parte inferior. Puedes empezar a escribir inmediatamente, como en cualquier editor de texto normal.
Los atajos que debes conocer
Nano muestra sus atajos en la parte inferior de la pantalla. El símbolo ^ significa la tecla Ctrl y M- significa la tecla Alt. Estos son los más importantes:
| Comando | Descripción |
|---|---|
| Ctrl + O | Guardar el archivo (te pide confirmar el nombre) |
| Ctrl + X | Salir de Nano (si hay cambios sin guardar, te pregunta) |
| Ctrl + K | Cortar la línea completa donde está el cursor |
| Ctrl + U | Pegar la línea cortada |
| Ctrl + W | Buscar texto dentro del archivo |
| Ctrl + \ | Buscar y reemplazar texto |
| Ctrl + G | Mostrar la ayuda completa |
| Ctrl + C | Mostrar en qué línea y columna está el cursor |
| Alt + U | Deshacer el último cambio |
| Alt + E | Rehacer (volver a aplicar un cambio deshecho) |
El flujo más común en Nano
El 90% de las veces harás lo mismo: abrir el archivo, hacer tus cambios, presionar Ctrl + O para guardar, presionar Enter para confirmar, y luego Ctrl + X para salir. Practica esta secuencia hasta que sea automática.
Ejemplo práctico: crear tu primer script
Vamos a crear un pequeño script usando Nano. Esto combina lo que aprendiste en módulos anteriores con la edición de archivos:
# Abre Nano para crear un nuevo archivonano mi-script.shDentro de Nano, escribe exactamente esto:
#!/bin/bashecho "¡Mi primer script!"echo "Fecha: $(date)"echo "Usuario: $(whoami)"echo "Estoy en: $(pwd)"Ahora guarda y sal:
- Presiona
Ctrl + O(guardar) - Presiona
Enter(confirmar nombre del archivo) - Presiona
Ctrl + X(salir)
Finalmente, haz el script ejecutable y ejecútalo:
chmod +x mi-script.sh./mi-script.shDeberías ver algo como:
¡Mi primer script!Fecha: sáb 14 feb 2026 15:30:00Usuario: tu-usuarioEstoy en: /home/tu-usuarioVim: el editor potente
Vim es un editor completamente diferente a Nano. Es extremadamente potente y eficiente una vez que lo dominas, pero tiene una curva de aprendizaje pronunciada. La razón principal para conocerlo es que viene instalado en prácticamente todos los sistemas Linux, incluyendo servidores donde Nano podría no estar disponible.
¿Necesito aprender Vim?
Para empezar, no. Nano es suficiente para la mayoría de las tareas. Pero es muy útil conocer los comandos básicos de Vim porque eventualmente te encontrarás en un servidor donde sea la única opción disponible. Aquí aprenderás solo lo esencial para no quedarte atrapado.
El concepto de modos
Lo que hace a Vim confuso al principio es que tiene modos. En Nano, puedes escribir apenas lo abres. En Vim, cuando lo abres estás en modo Normal, donde las teclas no escriben texto sino que ejecutan comandos. Para escribir, necesitas cambiar al modo Inserción.
| Modo | Cómo entrar | Para qué sirve |
|---|---|---|
| Normal | Presiona Esc | Navegar por el archivo, copiar, pegar, eliminar líneas |
| Inserción | Presiona i | Escribir texto, como en un editor normal |
| Comando | Escribe : (desde modo Normal) | Guardar, salir, buscar, configurar |
El flujo básico: abrir, editar, guardar, salir
Aquí está la secuencia completa para editar un archivo con Vim. Sigue estos pasos exactamente:
# Paso 1: Abrir el archivovim archivo.txt# Paso 2: Vim se abre en modo Normal (no puedes escribir todavía)# Presiona la tecla i para entrar en modo Inserción# Verás -- INSERT -- en la parte inferior de la pantalla
# Paso 3: Escribe lo que necesites (ahora sí puedes escribir)
# Paso 4: Cuando termines de escribir, presiona Esc# para volver al modo Normal
# Paso 5: Escribe :wq y presiona Enter para guardar y salir# :w = write (guardar), :q = quit (salir)¿Atrapado en Vim?
Es uno de los memes más famosos de la programación: “¿Cómo salgo de Vim?”. Si alguna vez te quedas atrapado, presiona Esc varias veces (para asegurarte de estar en modo Normal) y luego escribe :q! y presiona Enter. El signo de exclamación significa “salir sin guardar, no me importan los cambios”. Esto te sacará siempre.
Comandos esenciales de Vim
No necesitas memorizar todos estos ahora. Solo conócelos como referencia para cuando los necesites:
| Comando | Descripción |
|---|---|
| i | Entrar en modo inserción (escribir antes del cursor) |
| a | Entrar en modo inserción (escribir después del cursor) |
| Esc | Volver al modo normal (dejar de escribir) |
| :w | Guardar el archivo |
| :q | Salir (solo si no hay cambios sin guardar) |
| :wq | Guardar y salir |
| :q! | Salir SIN guardar (forzar salida) |
| dd | Eliminar la línea completa (en modo normal) |
| yy | Copiar la línea completa |
| p | Pegar debajo de la línea actual |
| u | Deshacer el último cambio |
| /texto | Buscar 'texto' hacia adelante |
| n | Ir a la siguiente coincidencia |
| G | Ir al final del archivo |
| gg | Ir al inicio del archivo |
¿Cuándo usar cada editor?
| Situación | Recomendación |
|---|---|
| Edición rápida de un archivo de configuración | Nano — abre, edita, guarda, listo |
| Servidor remoto donde nano no está instalado | Vim — siempre disponible |
| Estás empezando a aprender terminal | Nano — sin curva de aprendizaje |
| Quieres máxima productividad a largo plazo | Vim — pero requiere semanas de práctica |
| Editar archivos de código de un proyecto | Un editor gráfico (VS Code, etc.) — mejor experiencia |
Consejo para ciencia de datos
En tu trabajo diario de ciencia de datos, probablemente usarás VS Code, RStudio o Jupyter. Los editores de terminal son para ediciones rápidas de configuración (como .bashrc, archivos .env, o config.yaml) y para trabajar en servidores. No intentes desarrollar proyectos completos en Nano o Vim si tienes acceso a un editor gráfico.
Ejercicios del módulo
- Abre Nano con
nano prueba-nano.txt, escribe tres líneas de texto cualquiera, guarda conCtrl + O+ Enter, y sal conCtrl + X. Verifica concat prueba-nano.txt. - Vuelve a abrir el archivo con
nano prueba-nano.txt. UsaCtrl + Kpara cortar una línea yCtrl + Upara pegarla en otro lugar. Guarda y sal. - Abre Nano y usa
Ctrl + Wpara buscar una palabra dentro del archivo. ¿La encuentra? - Crea el script
mi-script.shque mostramos en el ejemplo práctico. Dale permisos de ejecución y ejecútalo. - Modifica
mi-script.shcon Nano para agregar una línea que digaecho "Directorio home: $HOME". Guarda y ejecuta de nuevo. - Abre Vim con
vim prueba-vim.txt. Presionai, escribe “Hola desde Vim”, presionaEsc, escribe:wqy presiona Enter. Verifica concat prueba-vim.txt. - Abre el mismo archivo en Vim. Practica la “salida de emergencia”: presiona
Escvarias veces y luego escribe:q!+ Enter. - Desafío: Crea un script con Nano que muestre la fecha, tu usuario, y cuántos archivos hay en el directorio actual (pista: usa
ls | wc -l).
Permisos y administración
En Linux, cada archivo y cada carpeta tiene permisos que determinan quién puede hacer qué con ellos. Esto es una de las bases de la seguridad del sistema: gracias a los permisos, otros usuarios no pueden leer tus archivos privados, los programas no pueden modificar archivos del sistema sin autorización, y tú mismo estás protegido de borrar cosas importantes por accidente.
Si vienes de Windows o macOS, probablemente nunca te has preocupado por permisos. En Linux, entenderlos es fundamental, especialmente cuando trabajas con scripts, servidores o datos sensibles. Al principio puede parecer complicado, pero en la práctica usarás los mismos patrones una y otra vez. Vamos paso a paso.
Entender los permisos desde la terminal
Los tres tipos de permisos
Cada archivo o carpeta en Linux tiene tres permisos fundamentales. Es importante entender que significan cosas distintas dependiendo de si se aplican a un archivo o a una carpeta:
| Permiso | Letra | En un archivo | En una carpeta |
|---|---|---|---|
| Lectura | r | Puedes ver el contenido (abrirlo, copiarlo) | Puedes listar qué hay dentro (ls) |
| Escritura | w | Puedes modificar o sobreescribir el contenido | Puedes crear, renombrar o eliminar archivos dentro |
| Ejecución | x | Puedes ejecutarlo como programa o script | Puedes entrar a la carpeta con cd |
Veamos esto con ejemplos concretos para que quede claro:
- Un archivo con permiso
rpero sinw: puedes leerlo, pero no editarlo. Imagina un documento de referencia que no quieres que nadie modifique. - Un script
.shsin permisox: aunque tenga código válido, la terminal te dirá “Permiso denegado” al intentar ejecutarlo. Necesitas darlexpara que funcione. - Una carpeta sin permiso
x: no puedes ni entrar concdni acceder a los archivos de dentro, aunque tengasrpara listarla. Es como tener la lista de contenido de una caja fuerte pero no la llave para abrirla. - Una carpeta con
xpero sinr: puedes entrar si conoces el nombre exacto de lo que buscas, pero no puedes listar su contenido. Es como una habitación oscura donde solo encuentras algo si sabes exactamente dónde está.
¿Por qué importa esto para ciencia de datos?
Cuando trabajas con datos, los permisos te ayudan a proteger información sensible (datos de pacientes, credenciales de bases de datos, API keys). Un archivo con permisos 600 significa que solo tú puedes leerlo. Esto no es opcional: muchas herramientas como SSH se niegan a funcionar si tus claves privadas tienen permisos demasiado abiertos.
Las tres categorías de usuarios
Los permisos se aplican a tres grupos de personas diferentes:
| Categoría | Letra | ¿Quién es? | Ejemplo |
|---|---|---|---|
| Owner | u | El dueño del archivo (generalmente quien lo creó) | Tú, cuando creas un script |
| Group | g | Un grupo de usuarios al que pertenece el archivo | Tu equipo de trabajo |
| Others | o | Todos los demás usuarios del sistema | Cualquier otra persona con acceso al servidor |
Esto significa que un archivo puede tener permisos distintos para cada categoría. Por ejemplo, tú (owner) puedes leer y editar un archivo, tu equipo (group) solo puede leerlo, y el resto (others) no puede ni verlo.
Identificar permisos con ls -l
Esta es la habilidad más práctica: saber leer los permisos de cualquier archivo o carpeta. Cuando ejecutas ls -l, la primera columna muestra los permisos. Puede parecer críptico al principio, pero tiene una estructura muy clara:
ls -l mi-script.sh# -rwxr-xr-- 1 paulo users 256 ene 15 10:30 mi-script.shDesglosemos esa cadena -rwxr-xr-- carácter por carácter:
- rwx r-x r--│ │ │ ││ │ │ └── Others (otros): r-- = solo pueden leer│ │ └────── Group (grupo): r-x = pueden leer y ejecutar│ └────────── Owner (dueño): rwx = puede leer, escribir y ejecutar└──────────── Tipo: - = archivo normal (d = directorio, l = enlace)El primer carácter indica el tipo del elemento:
-= archivo normald= directorio (carpeta)l= enlace simbólico (un atajo a otro archivo)
Los siguientes 9 caracteres se leen en grupos de tres, siempre en el mismo orden: r (lectura), w (escritura), x (ejecución). Si hay un guión - en lugar de una letra, ese permiso está desactivado.
Veamos varios ejemplos para entrenar el ojo:
ls -l# drwxr-xr-x carpeta/ ← directorio: todos pueden entrar y listar# -rw-r--r-- documento.txt ← archivo: todos leen, solo el dueño edita# -rwxr-xr-x programa ← ejecutable por todos# -rw------- clave-privada.pem ← archivo privado: SOLO el dueño accede# drwx------ .ssh/ ← carpeta privada: solo el dueño puede entrar# -rwxrwxrwx peligroso.sh ← ¡cualquiera puede modificar y ejecutar!Practica leyendo permisos
Ejecuta ls -la en tu directorio home y trata de leer los permisos de cada archivo. Identifica cuáles son carpetas (d), cuáles son privados (solo rw para el dueño), y cuáles son ejecutables (tienen x). Con práctica, leerás la cadena de permisos de un vistazo.
Otros datos que muestra ls -l
Además de los permisos, ls -l muestra información útil en cada columna:
-rwxr-xr-- 1 paulo users 256 ene 15 10:30 mi-script.sh│ │ │ │ │ │ ││ │ │ │ │ │ └── Nombre del archivo│ │ │ │ │ └── Fecha de última modificación│ │ │ │ └── Tamaño en bytes│ │ │ └── Grupo propietario│ │ └── Dueño (owner)│ └── Número de enlaces└── PermisosEsto es especialmente útil para verificar quién es el dueño de un archivo y cuándo fue modificado por última vez.
Modificar permisos con chmod
El comando chmod (de “change mode”) es el que usarás para cambiar los permisos de archivos y carpetas. Hay dos formas de usarlo: el modo simbólico (con letras, más intuitivo) y el modo octal (con números, más rápido). Ambos hacen lo mismo, solo cambia la forma de expresarlo.
Cuidado al cambiar permisos
Cambiar permisos incorrectamente puede tener consecuencias serias:
- Dar permisos excesivos (
chmod 777) a archivos sensibles expone datos privados a todos los usuarios del sistema. - Quitar permisos de ejecución a archivos del sistema puede dejar programas inutilizables.
- Cambiar permisos recursivamente (
chmod -R) en la carpeta equivocada puede afectar cientos de archivos de golpe. - Nunca ejecutes
chmod -R 777 /— esto elimina todas las protecciones del sistema operativo completo.
Regla de oro: da los permisos mínimos necesarios. Si solo tú necesitas leer un archivo, usa 600, no 644.
Modo simbólico (con letras)
El modo simbólico es el más fácil de entender porque usas letras que ya conoces. La sintaxis es:
chmod [quién][operación][permiso] archivoQuién:
u= owner (dueño)g= group (grupo)o= others (otros)a= all (todos, equivale au,gyojuntos)
Operación:
+= agregar un permiso-= quitar un permiso== establecer permisos exactos (reemplaza los anteriores)
Permiso:
r= lecturaw= escriturax= ejecución
Veamos ejemplos prácticos:
# Dar permiso de ejecución al dueñochmod u+x script.sh# Antes: -rw-r--r-- → Después: -rwxr--r--
# Quitar permiso de escritura a otroschmod o-w archivo.txt# Antes: -rw-r--rw- → Después: -rw-r--r--
# Dar lectura y ejecución al grupochmod g+rx programa# Antes: -rwx------ → Después: -rwxr-x---
# Dar permiso de ejecución a TODOSchmod a+x script.sh# Equivalente a: chmod u+x,g+x,o+x script.sh
# Establecer permisos EXACTOS para el dueño (reemplaza los anteriores)chmod u=rw archivo.txt# El dueño tendrá SOLO lectura y escritura, sin importar lo que tenía antes
# Quitar TODOS los permisos a otroschmod o= secreto.txt# Antes: -rw-r--r-- → Después: -rw-r-----
# Combinación: dar todo al dueño, solo lectura al restochmod u=rwx,g=r,o=r programaEl caso más común
La situación más frecuente es hacer un script ejecutable después de crearlo:
chmod +x mi-script.shCuando no especificas quién (u/g/o), se aplica a todos. Este comando lo usarás constantemente al crear scripts de Bash.
Modo octal (con números)
El modo numérico es más rápido y es el estándar cuando necesitas establecer todos los permisos de una sola vez. Cada permiso tiene un valor numérico:
| Permiso | Valor |
|---|---|
Lectura (r) | 4 |
Escritura (w) | 2 |
Ejecución (x) | 1 |
| Sin permiso | 0 |
Para calcular el número de cada categoría, sumas los valores de los permisos que quieres activar. Luego escribes tres dígitos: uno para el dueño, otro para el grupo y otro para otros.
Veamos un ejemplo paso a paso:
Queremos: rwxr-xr--
Owner: r + w + x = 4 + 2 + 1 = 7 Group: r + - + x = 4 + 0 + 1 = 5 Others: r + - + - = 4 + 0 + 0 = 4
Resultado: chmod 754 archivoOtro ejemplo, esta vez queremos que solo el dueño pueda leer y escribir:
Queremos: rw-------
Owner: r + w + - = 4 + 2 + 0 = 6 Group: - + - + - = 0 + 0 + 0 = 0 Others: - + - + - = 0 + 0 + 0 = 0
Resultado: chmod 600 archivoEsta es la tabla de combinaciones más útiles. No necesitas memorizar todas: con el tiempo las más comunes se vuelven automáticas:
| Número | Permisos | Significado |
|---|---|---|
7 | rwx | Todos los permisos |
6 | rw- | Lectura y escritura |
5 | r-x | Lectura y ejecución |
4 | r-- | Solo lectura |
0 | --- | Sin permisos |
Y los permisos completos más comunes que usarás en la práctica:
| Comando | Descripción |
|---|---|
| chmod 755 script.sh | rwxr-xr-x — Scripts y programas: todos ejecutan, solo el dueño edita |
| chmod 644 archivo.txt | rw-r--r-- — Archivos normales: todos leen, solo el dueño edita |
| chmod 700 carpeta/ | rwx------ — Carpeta privada: solo el dueño tiene acceso |
| chmod 600 clave.pem | rw------- — Archivo sensible: solo el dueño lee y escribe |
| chmod 444 referencia.txt | r--r--r-- — Solo lectura para todos (protección contra edición) |
¿Cuál modo usar?
Para acciones simples como “hacer ejecutable”, el modo simbólico es más fácil: chmod +x script.sh. Para establecer permisos exactos de una vez, el modo numérico es más preciso: chmod 755 script.sh. Con el tiempo usarás ambos según la situación.
Cambiar permisos en carpetas (modo recursivo)
Cuando cambias permisos de una carpeta, los archivos que están dentro no cambian automáticamente. Si quieres cambiar los permisos de una carpeta y todo lo que contiene, usas la opción -R (recursivo):
# Cambiar permisos de la carpeta Y todo lo de adentrochmod -R 755 mi-proyecto/
# Hacer privada una carpeta y todo su contenidochmod -R 700 datos-sensibles/Cuidado con chmod -R
El modo recursivo -R cambia permisos de todos los archivos y subcarpetas de golpe. Esto puede causar problemas:
- Si aplicas
755recursivamente, todos los archivos quedan como ejecutables (incluyendo.txt,.csv, etc.), lo cual no tiene sentido. - Si te equivocas de carpeta, puedes afectar archivos del sistema.
Para aplicar permisos diferentes a archivos y carpetas, usa find:
# Carpetas con 755 (se puede entrar y listar)find mi-proyecto/ -type d -exec chmod 755 {} \;
# Archivos con 644 (se puede leer pero no ejecutar)find mi-proyecto/ -type f -exec chmod 644 {} \;La máscara de permisos: umask
Cuando creas un archivo nuevo, ¿qué permisos tiene por defecto? Eso lo controla el umask. La máscara define qué permisos se quitan automáticamente al crear archivos y carpetas nuevos.
# Ver tu máscara actualumask# Salida típica: 0022El valor 0022 significa que a los archivos nuevos se les quita el permiso de escritura (2) para el grupo y para otros. En la práctica:
| Elemento | Permisos base | Menos umask 022 | Permisos reales |
|---|---|---|---|
| Archivos | 666 (rw-rw-rw-) | - 022 | 644 (rw-r—r—) |
| Carpetas | 777 (rwxrwxrwx) | - 022 | 755 (rwxr-xr-x) |
Esto explica por qué cuando creas un archivo con touch te sale rw-r--r-- y cuando creas una carpeta con mkdir te sale rwxr-xr-x.
Puedes cambiar el umask
Si trabajas con datos sensibles y quieres que los archivos nuevos sean privados por defecto:
# Solo el dueño puede leer y escribir archivos nuevosumask 077Esto solo afecta la sesión actual. Para hacerlo permanente, agrégalo a tu archivo ~/.bashrc.
Las máscaras más comunes:
| umask | Archivos nuevos | Carpetas nuevas | Uso típico |
|---|---|---|---|
022 | 644 (rw-r—r—) | 755 (rwxr-xr-x) | Valor por defecto en la mayoría de sistemas |
077 | 600 (rw-------) | 700 (rwx------) | Máxima privacidad |
002 | 664 (rw-rw-r—) | 775 (rwxrwxr-x) | Trabajo en equipo (grupo puede editar) |
El superusuario: sudo
En Linux, hay tareas que solo puede hacer el administrador (también llamado root o superusuario): instalar programas, modificar archivos del sistema, gestionar servicios, cambiar permisos de archivos que no te pertenecen, etc.
El comando sudo (de “Super User DO”) te permite ejecutar un solo comando con privilegios de administrador:
# Actualizar la lista de paquetes disponiblessudo apt update
# Instalar un programasudo apt install htop
# Editar un archivo de configuración del sistemasudo nano /etc/hostsCuando usas sudo, el sistema te pedirá tu contraseña. Esto es una medida de seguridad para confirmar que realmente eres tú. La contraseña se “recuerda” por unos minutos, así que no te la pedirá de nuevo inmediatamente.
¿Cuándo necesitas sudo?
La regla general es simple: necesitas sudo cuando quieres hacer algo fuera de tu directorio home o que afecta al sistema:
# Esto NO necesita sudo (es tu archivo, en tu carpeta)chmod 755 ~/mi-script.shnano ~/notas.txtmkdir ~/proyectos
# Esto SÍ necesita sudo (archivos del sistema o de otros usuarios)sudo chmod 644 /etc/configuracion.confsudo chown usuario:grupo /opt/datos/sudo apt install python3sudo es poder y responsabilidad
Con sudo puedes hacer cualquier cosa en el sistema, incluyendo destruirlo completamente. Algunas reglas de supervivencia:
- Nunca ejecutes
sudo rm -rf /ni variantes comosudo rm -rf /*— borra todo el sistema operativo. - Nunca copies comandos con
sudode internet sin entender qué hacen primero. Un comando malicioso consudopuede instalar software dañino o borrar tus datos. - Nunca uses
sudo chmod -R 777 /— elimina todas las protecciones de seguridad del sistema completo. - Si un comando no funciona sin
sudo, pregúntate por qué necesita permisos de administrador antes de agregarlo. Muchas veces el problema real es otro (ruta incorrecta, archivo inexistente, etc.). - Nunca trabajes permanentemente como root (
sudo su). Usasudosolo para comandos específicos.
Relación entre permisos y sudo
Aquí es donde todo se conecta. Los permisos definen qué puedes hacer como usuario normal. Cuando los permisos te bloquean, tienes dos opciones:
- Cambiar los permisos (si el archivo es tuyo):
chmod +x mi-script.sh - Usar
sudo(si el archivo no es tuyo o es del sistema):sudo nano /etc/hosts
# Intentas editar un archivo del sistemanano /etc/hostname# Error: permiso denegado (no eres root)
# Opción correcta: usar sudo para ese comando específicosudo nano /etc/hostnameUn truco útil: si olvidaste poner sudo al inicio de un comando y te dio error de permisos, puedes ejecutar sudo !! para repetir el último comando con sudo:
apt update# Error: permiso denegado
sudo !!# Equivale a: sudo apt updateCambiar propietario con chown
El comando chown (de “change owner”) cambia quién es el dueño de un archivo o carpeta. Siempre necesitas sudo para usarlo (salvo que estés cediendo algo que ya es tuyo):
# Cambiar solo el dueñosudo chown maria archivo.txt
# Cambiar dueño y grupo a la vezsudo chown maria:equipo-datos archivo.txt
# Cambiar recursivamente (carpeta y todo lo de adentro)sudo chown -R maria:equipo-datos proyecto/¿Cuándo necesitas chown? Principalmente cuando:
- Descargas archivos que quedaron con un dueño incorrecto
- Configuras carpetas compartidas en un servidor
- Mueves archivos entre usuarios
# Ver quién es el dueño actualls -l datos.csv# -rw-r--r-- 1 root root 1024 ene 15 10:30 datos.csv# ↑ ↑# dueño grupo → ¡El dueño es root! No puedes editarlo
# Cambiarlo a tu usuariosudo chown paulo:paulo datos.csv
# Ahora puedes editarlo sin sudonano datos.csv # ¡Funciona!Resumen visual de comandos
| Comando | Descripción |
|---|---|
| ls -l | Ver permisos, dueño, grupo y tamaño de archivos |
| ls -la | Igual pero incluyendo archivos ocultos |
| chmod +x archivo | Hacer un archivo ejecutable |
| chmod 755 archivo | Permisos rwxr-xr-x (script/programa) |
| chmod 644 archivo | Permisos rw-r--r-- (archivo normal) |
| chmod 600 archivo | Permisos rw------- (archivo privado) |
| chmod -R 700 carpeta/ | Permisos solo para el dueño, recursivamente |
| umask | Ver la máscara de permisos por defecto |
| sudo comando | Ejecutar un comando como administrador |
| sudo !! | Repetir el último comando con sudo |
| sudo chown usuario archivo | Cambiar el dueño de un archivo |
| sudo chown -R usuario:grupo carpeta/ | Cambiar dueño y grupo recursivamente |
Ejercicios del módulo
- Ejecuta
ls -laen tu directorio home. Observa la columna de permisos. Identifica al menos un directorio (d), un archivo oculto (empieza con.), y un archivo con permisos restrictivos. - Crea un archivo
secreto.txtconecho "datos confidenciales" > secreto.txt. Verifica sus permisos conls -l secreto.txt. ¿Qué permisos tiene por defecto? - Quita todos los permisos a otros usuarios:
chmod o-rwx secreto.txt. Verifica conls -l. ¿Cómo cambió la cadena de permisos? - Ahora ponle permisos
600(solo dueño lee y escribe):chmod 600 secreto.txt. Verifica conls -l. ¿Ves la diferencia con el paso anterior? - Crea un script:
echo '#!/bin/bash' > script-test.sh && echo 'echo "funciona"' >> script-test.sh. Intenta ejecutarlo con./script-test.sh. ¿Qué error te da y por qué? - Dale permisos de ejecución con
chmod +x script-test.sh. Ahora ejecútalo de nuevo. ¿Funciona? Verifica conls -lque laxapareció. - Usa
chmod 755 script-test.shy verifica conls -l. Luego usachmod 700 script-test.sh. ¿Cuál es la diferencia entre ambos? - Ejecuta
umaskpara ver tu máscara actual. Luego crea un archivo contouch nuevo.txty una carpeta conmkdir nueva-carpeta. Verifica los permisos de ambos conls -l. ¿Coinciden con lo que elumaskpredice? - Intenta editar
/etc/hostnameconnano /etc/hostname(sin sudo). ¿Qué pasa? Ahora intenta consudo nano /etc/hostname(pero sal sin guardar conCtrl + Xy luegoN). - Ejecuta
sudo whoami. ¿Qué usuario aparece? Compara conwhoamisin sudo. Esto demuestra quesudote convierte temporalmente en root. - Desafío 1: Calcula el número octal para los permisos
rwxr--r--. Crea un archivo y aplica esos permisos. Verifica conls -l. - Desafío 2: Crea una carpeta
proyecto/con tres archivos dentro. Usafindcon-exec chmodpara poner las carpetas en755y los archivos en644. Verifica conls -lR.
Gestión de procesos
¿Qué es un proceso?
Cada vez que ejecutas un comando o abres un programa, el sistema crea un proceso. Un proceso es simplemente un programa en ejecución. Tu navegador es un proceso, tu terminal es un proceso, e incluso cada comando que ejecutas crea un proceso temporalmente.
Cada proceso tiene un número identificador único llamado PID (Process ID). Este número es importante porque lo necesitarás si alguna vez necesitas detener un programa que se quedó colgado.
Ver los procesos activos: ps
El comando ps (de “process status”) te muestra los procesos en ejecución. Por sí solo muestra solo los procesos de tu terminal actual, pero con los flags aux muestra todos los procesos del sistema:
# Ver solo los procesos de tu terminalps
# Ver TODOS los procesos del sistema con detalleps auxLa salida de ps aux tiene mucha información. Veamos qué significa cada columna:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.0 0.1 169316 13092 ? Ss 10:00 0:02 /sbin/initpaulo 1234 2.5 1.2 987456 98765 ? Sl 10:05 1:30 node server.jspaulo 5678 0.0 0.0 12345 6789 pts/0 S 10:30 0:00 bash| Columna | Significado |
|---|---|
| USER | Quién ejecutó el proceso |
| PID | El número identificador del proceso |
| %CPU | Cuánto procesador está usando (porcentaje) |
| %MEM | Cuánta memoria está usando (porcentaje) |
| COMMAND | El comando o programa que se ejecutó |
En la práctica, rara vez leerás toda la lista. Normalmente combinas ps con grep para buscar un proceso específico:
# ¿Está corriendo Python?ps aux | grep "python"
# ¿Hay algún servidor Node.js activo?ps aux | grep "node"Monitor en tiempo real: top y htop
Mientras ps te muestra una foto instantánea, top te muestra los procesos en tiempo real, actualizándose cada pocos segundos. Es como el Administrador de Tareas de Windows o el Monitor de Actividad de macOS, pero en la terminal:
# Monitor básico (viene preinstalado en todos los sistemas)top
# Para salir de top, presiona qSin embargo, top es difícil de leer. htop es una versión mejorada con colores, barras visuales y mejor navegación:
# Instalar htopsudo apt install htop # Debian/Ubuntu/WSLbrew install htop # macOS
# Ejecutar htophtophtop es mucho mejor que top
Si puedes instalar htop, hazlo. Muestra el uso de CPU y memoria con barras de colores, permite ordenar por columna con un clic, y puedes matar procesos directamente desde la interfaz. Presiona q para salir, F6 para ordenar, y F9 para matar un proceso.
Terminar procesos: kill
A veces un programa se queda colgado o necesitas detener algo que está corriendo. Para eso usas kill seguido del PID del proceso:
# Primero, encuentra el PID del procesops aux | grep "nombre-del-programa"
# Terminar el proceso de forma amable (SIGTERM)kill 1234
# Si no responde, forzar la terminación (SIGKILL)kill -9 1234La diferencia entre kill y kill -9 es importante:
| Señal | Número | ¿Qué hace? |
|---|---|---|
| SIGTERM | 15 (por defecto) | Le pide al proceso que termine. El proceso puede guardar datos y cerrar correctamente |
| SIGKILL | 9 | Fuerza la terminación inmediata. El proceso no puede ignorar esta señal ni guardar nada |
Usa kill -9 solo como último recurso
Siempre intenta primero kill PID (sin el -9). Esto le da oportunidad al programa de cerrar correctamente, guardar archivos y liberar recursos. Solo usa kill -9 PID si el proceso no responde después de unos segundos. Matar un proceso con -9 puede causar pérdida de datos o archivos corruptos.
Si no quieres buscar el PID manualmente, puedes terminar procesos por su nombre:
# Terminar todos los procesos llamados "node"killall node
# Terminar un proceso que coincida con un patrónpkill -f "python script.py"Cuidado con killall
killall termina TODOS los procesos que coincidan con ese nombre. Si tienes 5 procesos de Node.js corriendo, killall node los termina todos. Asegúrate de que quieres terminar todos antes de usarlo.
Procesos en segundo plano
Normalmente, cuando ejecutas un comando, la terminal se “bloquea” hasta que el comando termina. No puedes escribir nada más hasta que finalice. Pero puedes ejecutar procesos en segundo plano para que la terminal quede libre:
# El & al final ejecuta el comando en segundo planosleep 60 &# [1] 5678 ← [número de job] PID
# La terminal queda libre para seguir trabajandoVeamos los comandos para gestionar procesos en segundo plano:
# Ver los procesos en segundo plano de esta terminaljobs# [1]+ Running sleep 60 &
# Traer un proceso al frente (vuelve a bloquear la terminal)fg %1
# Pausar el proceso actual: presiona Ctrl+Z# [1]+ Stopped sleep 60
# Continuar el proceso pausado, pero en segundo planobg %1Ejemplo práctico paso a paso
Imagina que quieres levantar un servidor web simple mientras sigues trabajando en la terminal:
# Iniciar un servidor HTTP en segundo planopython3 -m http.server 8000 &# [1] 5678
# Verificar que está corriendojobs# [1]+ Running python3 -m http.server 8000 &
# Seguir trabajando normalmente...lspwd
# Cuando quieras detenerlo, tráelo al frente y usa Ctrl+Cfg %1# Ctrl+C para detenerloAtajos de teclado importantes
Estos atajos funcionan con cualquier proceso que esté corriendo en tu terminal:
| Atajo | ¿Qué hace? |
|---|---|
| Ctrl + C | Interrumpe (mata) el proceso que está corriendo en primer plano |
| Ctrl + Z | Pausa el proceso actual y te devuelve al prompt |
| Ctrl + D | Envía señal de “fin de entrada” (cierra la terminal si no hay nada corriendo) |
Ctrl+C es tu botón de emergencia
Si algún comando se queda corriendo y no termina, o si ves que algo no va bien, presiona Ctrl + C. Esto interrumpe la mayoría de los programas inmediatamente. Es el equivalente a “forzar cierre” pero de forma segura. Úsalo sin miedo.
Resumen de comandos
| Comando | Descripción |
|---|---|
| ps aux | Listar todos los procesos del sistema |
| ps aux | grep nombre | Buscar un proceso específico |
| top | Monitor de procesos en tiempo real |
| htop | Monitor mejorado (necesita instalación) |
| kill PID | Terminar proceso de forma amable |
| kill -9 PID | Forzar terminación (último recurso) |
| killall nombre | Terminar todos los procesos con ese nombre |
| comando & | Ejecutar en segundo plano |
| jobs | Ver procesos en segundo plano |
| fg %N | Traer proceso N al frente |
| bg %N | Continuar proceso N en segundo plano |
| Ctrl+C | Interrumpir el proceso actual |
| Ctrl+Z | Pausar el proceso actual |
Ejercicios del módulo
- Ejecuta
ps(sin flags). ¿Cuántos procesos ves? ¿Qué procesos son? - Ahora ejecuta
ps aux. ¿Cuántos procesos hay en total? Usaps aux | wc -lpara contarlos. - Busca si tienes algún proceso de Bash corriendo:
ps aux | grep "bash". ¿Cuántos aparecen? - Ejecuta
topy observa qué procesos usan más CPU y memoria. Presiona q para salir. - Si tienes
htopinstalado, ejecútalo y compara contop. Si no lo tienes, instálalo consudo apt install htop. - Ejecuta
sleep 30 ¶ crear un proceso en segundo plano. Usajobspara verificar que está corriendo. Luego usafg %1para traerlo al frente y Ctrl+C para detenerlo. - Ejecuta
sleep 120 &. Busca su PID conps aux | grep sleep. Termínalo conkill PID. - Ejecuta
sleep 200 &, luego otrosleep 300 &. Usajobspara ver ambos. Mata el segundo conkill %2. - Ejecuta
cat(sin argumentos; se queda esperando entrada). Practica usar Ctrl+C para interrumpirlo. Luego ejecútalo de nuevo y usa Ctrl+Z para pausarlo. ¿Qué diferencia hay? - Desafío: Ejecuta
python3 -m http.server 9000 &(o cualquier comando de larga duración), verifica que está corriendo conjobsyps, y luego termínalo usando su PID.
Bash scripting
¿Qué es un script de Bash?
Hasta ahora has escrito comandos uno por uno en la terminal. Un script es simplemente un archivo de texto que contiene una serie de comandos que se ejecutan en secuencia. En lugar de escribir 10 comandos a mano, los pones todos en un archivo y lo ejecutas una sola vez.
Piensa en un script como una receta de cocina: es una lista de instrucciones paso a paso que el computador sigue automáticamente. Los scripts son increíblemente útiles para automatizar tareas repetitivas, como hacer respaldos, procesar archivos de datos, o configurar un entorno de trabajo.
¿Por qué Bash si ya existe Python y R?
Si vienes del mundo de ciencia de datos, probablemente te preguntas: ¿para qué aprender Bash scripting si puedo hacer todo en Python o R? La respuesta es que Bash no reemplaza a esos lenguajes, los coordina. Cada uno tiene su rol:
- Python/R: análisis, estadísticas, modelos, visualizaciones
- Bash: automatizar, conectar, mover archivos, preparar datos, orquestar
En la práctica, un flujo de trabajo real de ciencia de datos se ve así:
#!/bin/bash
echo "=== Pipeline de análisis de datos ==="echo "Inicio: $(date)"
# 1. Descargar los datos frescosecho "Descargando datos..."curl -s -o datos_raw.csv https://api.ejemplo.com/datos/export
# 2. Limpiar y transformar con Pythonecho "Limpiando datos con Python..."python3 limpiar_datos.py datos_raw.csv datos_limpios.csv
# 3. Análisis estadístico con Recho "Ejecutando análisis en R..."Rscript analisis_estadistico.R datos_limpios.csv resultados/
# 4. Generar reporteecho "Generando reporte..."python3 generar_reporte.py resultados/ reporte_final.html
echo "Pipeline completado: $(date)"echo "Reporte disponible en: reporte_final.html"Bash es el director de orquesta: descarga datos, llama a Python para limpiarlos, llama a R para analizarlos, y junta todo. Este patrón es la forma estándar de trabajar en Bioinformática, Data Science y DevOps.
Ejemplo real: Bioinformática
En bioinformática, un pipeline típico ejecuta una docena de herramientas diferentes en secuencia: descarga secuencias genómicas, las alinea con una herramienta en C++, las filtra con Python, hace estadísticas con R, y genera reportes en HTML. Todo coordinado por un script de Bash. Sin Bash, tendrías que ejecutar cada paso manualmente y acordarte del orden exacto.
Otro ejemplo más simple pero muy útil: preparar tu entorno de trabajo cada día:
#!/bin/bash
# Script para iniciar tu día de trabajo en un proyecto de datosecho "Preparando entorno de trabajo..."
# Activar el entorno virtual de Pythonsource ~/envs/mi-proyecto/bin/activate
# Ir al directorio del proyectocd ~/proyectos/analisis-salud
# Descargar datos actualizadosecho "Descargando datos del día..."python3 descargar_datos.py
# Abrir Jupyter Notebookecho "Abriendo Jupyter..."jupyter notebook &
echo "¡Todo listo! Jupyter se abrió en tu navegador."En lugar de recordar y escribir 5 comandos cada mañana, ejecutas ./iniciar-proyecto.sh y todo se prepara solo.
Tu primer script
Vamos a crear un script simple paso a paso. Abre Nano y crea un archivo llamado hola.sh:
nano hola.shEscribe lo siguiente:
#!/bin/bash
# Mi primer script de Bashecho "¡Hola desde mi script!"echo "Hoy es $(date)"echo "Estás en: $(pwd)"Guarda con Ctrl + O + Enter y sal con Ctrl + X.
Antes de poder ejecutarlo, necesitas dos pasos:
# Paso 1: Dar permiso de ejecuciónchmod +x hola.sh
# Paso 2: Ejecutar el script./hola.shEl shebang: #!/bin/bash
La primera línea #!/bin/bash se llama shebang (o hashbang). Es la línea más importante de cualquier script porque le dice al sistema operativo qué programa debe usar para interpretar las instrucciones que siguen.
#!/bin/bash ← "Usa Bash para ejecutar este script"Sin el shebang, el sistema podría intentar ejecutar tu script con el shell equivocado, o directamente no saber qué hacer con él. Siempre incluye el shebang como primera línea.
El shebang no es exclusivo de Bash. Esto es lo que hace tan poderoso el concepto: puedes tener scripts en diferentes lenguajes y el sistema sabe cómo ejecutar cada uno:
#!/bin/bash # Script de Bash#!/usr/bin/env python3 # Script de Python#!/usr/bin/env Rscript # Script de R#!/usr/bin/env node # Script de Node.js¿Por qué /usr/bin/env?
Para Python, R y otros lenguajes, es mejor usar #!/usr/bin/env python3 en vez de #!/usr/bin/python3. La versión con env busca el programa en tu PATH, así funciona aunque Python esté instalado en una ruta diferente (como en un entorno virtual). Para Bash usamos #!/bin/bash directamente porque Bash siempre está en /bin/bash en sistemas Linux.
Rutas al ejecutar scripts: ./ y por qué importa
¿Por qué escribimos ./hola.sh y no simplemente hola.sh? Este es un punto que confunde a muchos al principio, pero es fundamental entenderlo.
Cuando escribes un comando en la terminal, el sistema lo busca en una lista de carpetas predefinidas (el PATH). Puedes ver esas carpetas con:
echo $PATHSi escribes ls, la terminal busca en esas carpetas, encuentra /usr/bin/ls, y lo ejecuta. Pero tu script hola.sh no está en ninguna de esas carpetas — está en tu directorio actual. Por eso necesitas decirle explícitamente dónde está:
# Esto NO funciona (busca hola.sh en el PATH del sistema)hola.sh# Error: command not found
# Esto SÍ funciona (el ./ significa "en el directorio actual")./hola.sh
# Esto también funciona (ruta completa)/home/paulo/scripts/hola.sh
# Y esto también (ruta relativa desde otro lugar)../scripts/hola.shRepasemos los tipos de rutas, porque entender esto te ahorrará muchos dolores de cabeza:
Ruta absoluta: empieza desde la raíz del sistema (/). Siempre funciona sin importar dónde estés:
/home/paulo/proyectos/analisis/script.sh/home/paulo/datos/pacientes.csvRuta relativa: parte desde tu directorio actual. Cambia según dónde estés:
./script.sh # En el directorio actual../datos/pacientes.csv # Un nivel arriba, luego en datos/scripts/procesar.sh # Dentro de la subcarpeta scripts/Atajos útiles:
. # Directorio actual.. # Directorio padre (un nivel arriba)~ # Tu directorio home (/home/tu-usuario)Las rutas dentro de un script son relativas a DONDE lo ejecutas
Este es uno de los errores más comunes. Si tu script hace referencia a datos/archivo.csv, esa ruta es relativa al directorio desde donde ejecutas el script, no a donde está el script. Ejemplo:
# Tu script está en ~/proyectos/scripts/procesar.sh# Y dentro tiene: python3 limpiar.py datos/raw.csv
# Si lo ejecutas desde ~/proyectos/scripts/cd ~/proyectos/scripts/./procesar.sh # Busca datos/raw.csv dentro de scripts/ ← ¡NO EXISTE!
# Si lo ejecutas desde ~/proyectos/cd ~/proyectos/./scripts/procesar.sh # Busca datos/raw.csv dentro de proyectos/ ← ¡CORRECTO!Para evitar este problema, usa rutas absolutas dentro de tus scripts, o usa este truco al inicio del script para cambiar al directorio donde está el archivo:
#!/bin/bash# Ir al directorio donde está este scriptcd "$(dirname "$0")"Veamos un ejemplo práctico. Imagina esta estructura de proyecto:
mi-proyecto/├── scripts/│ ├── limpiar.sh│ └── analizar.sh├── datos/│ ├── raw/│ │ └── encuesta.csv│ └── procesados/└── resultados/Dentro de limpiar.sh, podrías escribir las rutas de dos formas:
#!/bin/bash# Esto solo funciona si ejecutas desde mi-proyecto/python3 scripts/limpiar_datos.py datos/raw/encuesta.csv datos/procesados/encuesta_limpia.csv#!/bin/bash# Primero nos ubicamos en la raíz del proyectocd "$(dirname "$0")/.."
# Ahora las rutas son predeciblespython3 scripts/limpiar_datos.py datos/raw/encuesta.csv datos/procesados/encuesta_limpia.csv
echo "Datos procesados en: $(pwd)/datos/procesados/"La línea cd "$(dirname "$0")/.." hace lo siguiente:
$0= la ruta con la que se llamó al script (ej:./scripts/limpiar.sh)dirname "$0"= el directorio donde está el script (ej:./scripts)/.."= subir un nivel (al directorio del proyecto)
Así el script siempre funciona sin importar desde dónde lo ejecutes.
Variables
Las variables te permiten guardar información para usarla más adelante. En Bash, asignas una variable con el signo = y la usas poniendo $ antes del nombre:
#!/bin/bash
# Asignar variablesnombre="Paulo"edad=30fecha=$(date +%Y-%m-%d)
# Usar variables con $echo "Hola, $nombre"echo "Tienes $edad años"echo "Fecha: $fecha"
# Usar llaves para delimitar el nombre de la variableecho "Archivo: ${nombre}_backup.txt"Sin espacios alrededor del =
En Bash, la asignación de variables no puede tener espacios alrededor del =. Esto es correcto: nombre="Paulo". Esto dará error: nombre = "Paulo". Es uno de los errores más comunes cuando empiezas con scripting.
Las llaves ${nombre} son necesarias cuando la variable va pegada a otro texto. Sin las llaves, $nombre_backup buscaría una variable llamada nombre_backup (que no existe), en lugar de usar la variable nombre seguida del texto _backup.
Variables especiales
Bash tiene variables especiales que se crean automáticamente. Son especialmente útiles cuando tu script recibe información desde la línea de comandos:
| Variable | Significado |
|---|---|
$0 | El nombre del script |
$1, $2, ... | Los argumentos que le pasaste al script |
$# | La cantidad de argumentos |
$@ | Todos los argumentos juntos |
$? | El código de salida del último comando (0 = éxito, otro = error) |
Veamos cómo funcionan con un ejemplo:
#!/bin/bash
echo "Este script se llama: $0"echo "Primer argumento: $1"echo "Segundo argumento: $2"echo "Recibí $# argumentos en total"echo "Todos los argumentos: $@"chmod +x argumentos.sh./argumentos.sh hola mundo# Primer argumento: hola# Segundo argumento: mundo# Recibí 2 argumentos en total# Todos los argumentos: hola mundoLeer entrada del usuario con read
A veces quieres que tu script le haga preguntas al usuario y espere su respuesta. Para eso usas read:
#!/bin/bash
echo "¿Cómo te llamas?"read nombre
echo "¿Cuántos años tienes?"read edad
echo "¡Hola, $nombre! Tienes $edad años."Puedes hacer lo mismo de forma más compacta con read -p, que muestra el mensaje y espera la respuesta en la misma línea:
read -p "Ingresa tu nombre: " nombreecho "Hola, $nombre"
# Para passwords (no muestra lo que escribes)read -sp "Ingresa tu contraseña: " passwordecho # salto de línea (porque -s oculta el Enter también)echo "Contraseña recibida"Condicionales: tomar decisiones con if
Los condicionales permiten que tu script tome decisiones: “si se cumple esta condición, haz esto; si no, haz esto otro”. La estructura básica es:
if [ condición ]; then # código si la condición es verdaderaelif [ otra_condición ]; then # código si la segunda condición es verdaderaelse # código si ninguna condición se cumpliófiLos espacios son obligatorios
Dentro de los corchetes [ ], los espacios son obligatorios. [ "$edad" -ge 18 ] es correcto. ["$edad" -ge 18] dará error. Esto es uno de los aspectos más confusos de Bash para principiantes, pero es una regla simple: siempre deja un espacio después de [ y antes de ].
Veamos un ejemplo completo:
#!/bin/bash
read -p "¿Cuántos años tienes? " edad
if [ "$edad" -ge 18 ]; then echo "Eres mayor de edad"elif [ "$edad" -ge 13 ]; then echo "Eres adolescente"else echo "Eres menor de edad"fiOperadores de comparación para números
| Operador | Significado | Ejemplo |
|---|---|---|
-eq | Igual a | [ "$a" -eq 5 ] |
-ne | No igual a | [ "$a" -ne 0 ] |
-gt | Mayor que | [ "$a" -gt 10 ] |
-ge | Mayor o igual que | [ "$a" -ge 18 ] |
-lt | Menor que | [ "$a" -lt 0 ] |
-le | Menor o igual que | [ "$a" -le 100 ] |
Operadores para texto (strings)
| Operador | Significado | Ejemplo |
|---|---|---|
= | Textos iguales | [ "$nombre" = "Paulo" ] |
!= | Textos diferentes | [ "$respuesta" != "no" ] |
-z | Texto vacío | [ -z "$variable" ] |
-n | Texto no vacío | [ -n "$variable" ] |
Operadores para archivos
Estos son especialmente útiles para scripts que trabajan con archivos:
| Operador | Significado | Ejemplo |
|---|---|---|
-f | Existe y es un archivo | [ -f "datos.csv" ] |
-d | Existe y es un directorio | [ -d "carpeta" ] |
-e | Existe (archivo o directorio) | [ -e "algo" ] |
-r | Tiene permiso de lectura | [ -r "archivo" ] |
-w | Tiene permiso de escritura | [ -w "archivo" ] |
-x | Tiene permiso de ejecución | [ -x "script.sh" ] |
#!/bin/bash
archivo=$1
# Verificar que se proporcionó un argumentoif [ -z "$archivo" ]; then echo "Uso: $0 <nombre-de-archivo>" echo "Ejemplo: $0 datos.csv" exit 1fi
# Verificar qué esif [ -f "$archivo" ]; then lineas=$(wc -l < "$archivo") echo "'$archivo' es un archivo con $lineas líneas"elif [ -d "$archivo" ]; then echo "'$archivo' es un directorio"else echo "'$archivo' no existe"fiBucle for: repetir acciones
El bucle for repite una acción para cada elemento de una lista. Es como decir “para cada X, haz Y”:
#!/bin/bash
# Iterar sobre una lista de palabrasfor fruta in manzana pera naranja; do echo "Fruta: $fruta"done# Fruta: manzana# Fruta: pera# Fruta: naranjaLos usos más prácticos de for son recorrer archivos y rangos numéricos:
# Procesar todos los archivos .txt del directoriofor archivo in *.txt; do echo "Procesando: $archivo" wc -l "$archivo"done
# Contar del 1 al 5for i in {1..5}; do echo "Número: $i"done
# Estilo C (si vienes de otro lenguaje)for ((i = 0; i < 5; i++)); do echo "Índice: $i"doneEjemplo práctico: renombrar archivos en lote
#!/bin/bash
# Renombrar todos los .txt a .mdfor archivo in *.txt; do # Verificar que realmente hay archivos .txt [ -f "$archivo" ] || continue
nuevo="${archivo%.txt}.md" mv "$archivo" "$nuevo" echo "Renombrado: $archivo → $nuevo"doneLa expresión ${archivo%.txt} elimina .txt del final del nombre. Luego le agregamos .md. Es una forma muy útil de manipular nombres de archivo en Bash.
Bucle while: repetir mientras se cumpla una condición
A diferencia de for (que recorre una lista), while repite una acción mientras una condición sea verdadera:
#!/bin/bash
# Contador simplecontador=1while [ "$contador" -le 5 ]; do echo "Contando: $contador" ((contador++))doneUn uso muy práctico de while es leer un archivo línea por línea:
# Leer cada línea de un archivowhile IFS= read -r linea; do echo "Línea: $linea"done < archivo.txtMenú interactivo con while y case
Este es un patrón muy común en scripts de Bash: un menú que se repite hasta que el usuario elige salir:
#!/bin/bash
while true; do echo "" echo "=== MENÚ ===" echo "1) Mostrar fecha" echo "2) Listar archivos" echo "3) Uso de disco" echo "4) Salir" read -p "Elige una opción: " opcion
case $opcion in 1) date ;; 2) ls -la ;; 3) df -h ;; 4) echo "¡Adiós!"; break ;; *) echo "Opción no válida, intenta de nuevo" ;; esacdonecase es la versión Bash de un “switch”: compara el valor de $opcion con cada patrón y ejecuta el código correspondiente. El * es el caso por defecto (si no coincide con nada).
Funciones: reutilizar código
Las funciones te permiten agrupar comandos bajo un nombre y reutilizarlos. Si te encuentras repitiendo el mismo bloque de código varias veces, ponlo en una función:
#!/bin/bash
# Definir una funciónsaludar() { echo "¡Hola, $1!"}
# Llamar a la funciónsaludar "Paulo"saludar "María"# ¡Hola, Paulo!# ¡Hola, María!Los argumentos de las funciones funcionan igual que los del script: $1 es el primer argumento, $2 el segundo, etc.
Ejemplo completo: script de respaldo
Ahora vamos a juntar todo lo que aprendimos en un script útil del mundo real. Este script crea un respaldo comprimido de una carpeta:
#!/bin/bash
# Script de respaldo simple# Uso: ./respaldo.sh [directorio-origen] [directorio-destino]
ORIGEN="${1:-.}"DESTINO="${2:-./respaldo}"FECHA=$(date +%Y%m%d_%H%M%S)ARCHIVO="respaldo_${FECHA}.tar.gz"
# Verificar que el directorio origen existeif [ ! -d "$ORIGEN" ]; then echo "Error: el directorio '$ORIGEN' no existe" exit 1fi
# Crear directorio destino si no existemkdir -p "$DESTINO"
echo "Creando respaldo de '$ORIGEN'..."
# Crear el archivo comprimidotar -czf "${DESTINO}/${ARCHIVO}" "$ORIGEN"
# Verificar si el comando tuvo éxitoif [ $? -eq 0 ]; then tamano=$(du -h "${DESTINO}/${ARCHIVO}" | cut -f1) echo "Respaldo creado exitosamente:" echo " Archivo: ${DESTINO}/${ARCHIVO}" echo " Tamaño: ${tamano}"else echo "Error al crear el respaldo" exit 1fichmod +x respaldo.sh./respaldo.sh ./mi-proyecto ./backups# Creando respaldo de './mi-proyecto'...# Respaldo creado exitosamente:# Archivo: ./backups/respaldo_20260214_153000.tar.gz# Tamaño: 2.5MAnalicemos las partes nuevas:
${1:-.}significa “usa el primer argumento, y si no hay ninguno, usa.” (directorio actual).tar -czfcrea un archivo comprimido (.tar.gz).-c= crear,-z= comprimir con gzip,-f= nombre del archivo.$?contiene el código de salida del último comando.0significa éxito, cualquier otro número significa error.
Bash como herramienta de ciencia de datos
Ya vimos cómo Bash coordina herramientas. Pero Bash también puede hacer procesamiento de datos básico por sí solo, sin necesidad de Python o R. Esto es útil para exploración rápida, limpieza preliminar, o cuando trabajas en un servidor sin entorno gráfico.
Explorar un CSV desde la terminal
#!/bin/bash
# Script para exploración rápida de un archivo CSVarchivo="${1:?Uso: $0 archivo.csv}"
if [ ! -f "$archivo" ]; then echo "Error: '$archivo' no existe" exit 1fi
echo "=== Exploración de $archivo ==="echo ""
# ¿Cuántas filas tiene? (restamos 1 por el encabezado)total=$(wc -l < "$archivo")filas=$((total - 1))echo "Filas de datos: $filas"
# ¿Cuántas columnas?columnas=$(head -1 "$archivo" | tr ',' '\n' | wc -l)echo "Columnas: $columnas"
# Mostrar los nombres de las columnasecho ""echo "Nombres de columnas:"head -1 "$archivo" | tr ',' '\n' | nl
# Primeras 5 filasecho ""echo "Primeras 5 filas:"head -6 "$archivo" | column -t -s ','
# Tamaño del archivotamano=$(du -h "$archivo" | cut -f1)echo ""echo "Tamaño: $tamano"chmod +x explorar-csv.sh./explorar-csv.sh datos_pacientes.csv# === Exploración de datos_pacientes.csv ===## Filas de datos: 1523# Columnas: 8## Nombres de columnas:# 1 id# 2 nombre# 3 edad# 4 diagnostico# ...Procesar múltiples archivos de datos
Imagina que recibes datos mensuales en archivos separados y necesitas unirlos:
#!/bin/bash
# Unir múltiples CSV en uno solo (mismo formato, con encabezado)directorio="${1:-.}"salida="${2:-datos_combinados.csv}"
# Tomar el encabezado del primer archivoprimer_archivo=$(ls "$directorio"/*.csv 2>/dev/null | head -1)
if [ -z "$primer_archivo" ]; then echo "No se encontraron archivos CSV en '$directorio'" exit 1fi
# Escribir encabezadohead -1 "$primer_archivo" > "$salida"
# Agregar datos de todos los archivos (sin encabezado)for archivo in "$directorio"/*.csv; do tail -n +2 "$archivo" >> "$salida" echo " Agregado: $archivo ($(tail -n +2 "$archivo" | wc -l) filas)"done
total=$(tail -n +2 "$salida" | wc -l)echo "Archivo combinado: $salida ($total filas totales)"¿Cuándo usar Bash vs Python para datos?
Usa Bash cuando necesites: exploración rápida (cuántas filas, qué columnas), unir/dividir archivos, renombrar archivos en lote, automatizar pipelines, descargar datos.
Usa Python/R cuando necesites: análisis estadístico, limpieza compleja, visualizaciones, machine learning, manipulación avanzada de DataFrames.
La combinación de ambos es lo más poderoso: Bash prepara y orquesta, Python/R analiza.
Ejercicios del módulo
- Crea un script
saludo.shque reciba un nombre como argumento ($1) y diga “¡Hola, [nombre]!”. Si no recibe argumento, que diga “¡Hola, mundo!”. - Crea un script
info.shque muestre tu usuario, la fecha, el directorio actual y cuántos archivos hay en él. - Crea un script que reciba un número como argumento y diga si es positivo, negativo o cero.
- Crea un script con
read -pque pida el nombre de un archivo y diga si existe o no (usa[ -f "$archivo" ]). - Crea un script con un bucle
forque cree 5 archivos:archivo1.txt,archivo2.txt, …,archivo5.txt. - Crea un script que recorra todos los archivos
.txtdel directorio actual y muestre cuántas líneas tiene cada uno. - Crea un menú interactivo con
whileycaseque tenga al menos 3 opciones útiles (fecha, archivos, espacio en disco, etc.). - Modifica el script de respaldo del ejemplo para que muestre un mensaje de confirmación antes de crear el respaldo (“¿Estás seguro? (s/n)”).
- Crea una función
contar_archivosque reciba un directorio como argumento y diga cuántos archivos contiene. - Crea un script
explorar.shque reciba un archivo CSV como argumento y muestre: número de filas, número de columnas, nombres de las columnas, y las primeras 3 filas de datos. - Desafío 1: Crea un script que reciba una extensión como argumento (ej:
txt) y cuente cuántos archivos con esa extensión hay en el directorio actual y sus subdirectorios (usafind). - Desafío 2: Crea un mini-pipeline: un script que (1) cree un archivo CSV de prueba con datos inventados, (2) llame a otro script que cuente las filas y columnas, y (3) muestre un resumen final. Practica la coordinación entre scripts.
Automatización con Cron
¿Qué es Cron?
Imagina que necesitas hacer un respaldo de tus datos todos los días a las 3 de la mañana, o limpiar archivos temporales cada semana. No vas a estar despierto para ejecutar esos comandos manualmente. Para eso existe Cron: un servicio de Linux que ejecuta tareas automáticamente en los horarios que tú definas.
Cron funciona como un despertador programable: tú le dices “ejecuta este comando a esta hora” y él se encarga de hacerlo, sin importar si estás frente al computador o no.
El crontab: tu agenda de tareas
Cada usuario tiene su propio crontab (tabla de cron), que es el archivo donde defines tus tareas programadas. Los comandos para gestionarlo son simples:
# Ver tus tareas programadas actualescrontab -l
# Editar tu crontab (abrir el editor para agregar/modificar tareas)crontab -e
# Eliminar TODAS tus tareas programadascrontab -rCuidado con crontab -r
El comando crontab -r elimina todas tus tareas programadas sin pedir confirmación. Si solo quieres eliminar una tarea, usa crontab -e y borra la línea correspondiente. Es muy fácil confundir -e (editar) con -r (remover) porque están al lado en el teclado.
Primera vez con crontab -e
La primera vez que ejecutes crontab -e, te pedirá elegir un editor de texto. Selecciona nano (generalmente es la opción 1). Si por accidente seleccionas Vim y no sabes usarlo, presiona Esc, escribe :q! y Enter para salir, luego ejecuta select-editor para cambiar el editor.
La sintaxis de Cron paso a paso
Cada línea del crontab tiene dos partes: cuándo ejecutar (5 campos de tiempo) y qué ejecutar (el comando). La estructura es:
┌───────── minuto (0-59)│ ┌─────── hora (0-23)│ │ ┌───── día del mes (1-31)│ │ │ ┌─── mes (1-12)│ │ │ │ ┌─ día de la semana (0-7, donde 0 y 7 = domingo)│ │ │ │ │* * * * * comando-a-ejecutarEl asterisco * significa “todos los valores posibles”. Así que * * * * * significa “cada minuto de cada hora de cada día de cada mes de cada día de la semana” (o sea, cada minuto).
Veamos los caracteres especiales que puedes usar:
| Carácter | Significado | Ejemplo |
|---|---|---|
* | Cualquier valor | * * * * * = cada minuto |
, | Lista de valores | 0,15,30,45 * * * * = minutos 0, 15, 30 y 45 |
- | Rango de valores | 0 9-17 * * * = cada hora de 9 AM a 5 PM |
/ | Cada N unidades | */5 * * * * = cada 5 minutos |
Ejemplos prácticos explicados
Veamos algunos ejemplos comunes, traduciéndolos a español:
# Cada minuto (útil para probar que cron funciona)* * * * * echo "test $(date)" >> /tmp/cron-test.log
# Todos los días a las 2:30 AM# (minuto 30, hora 2, cualquier día, cualquier mes, cualquier día de semana)30 2 * * * /home/usuario/scripts/respaldo.sh
# Cada lunes a las 9:00 AM# (minuto 0, hora 9, cualquier día del mes, cualquier mes, día 1=lunes)0 9 * * 1 /home/usuario/scripts/reporte-semanal.sh
# Cada 15 minutos*/15 * * * * /home/usuario/scripts/verificar-servicio.sh
# El primer día de cada mes a medianoche0 0 1 * * /home/usuario/scripts/limpieza-mensual.sh
# De lunes a viernes a las 8:00 AM0 8 * * 1-5 /home/usuario/scripts/recordatorio.sh
# Cada 6 horas (a las 0, 6, 12, 18)0 */6 * * * /home/usuario/scripts/sincronizar.shProbador de expresiones cron
Si no estás seguro de que tu expresión cron hace lo que quieres, usa crontab.guru. Es una herramienta web gratuita donde escribes la expresión y te dice en español cuándo se ejecutará. Úsala siempre antes de agregar una tarea a tu crontab.
Errores comunes y buenas prácticas
Cron ejecuta las tareas en un entorno mínimo: no carga tu archivo .bashrc, no tiene las mismas variables de entorno que tu terminal, y no sabe dónde están tus programas a menos que se lo digas explícitamente. Esto causa la mayoría de los problemas con cron.
Siempre usa rutas absolutas:
# MAL: cron no sabe dónde está "mi-script.sh"* * * * * mi-script.sh
# BIEN: ruta completa al script* * * * * /home/usuario/scripts/mi-script.sh
# MAL: cron podría no encontrar python3* * * * * python3 tarea.py
# BIEN: ruta completa a python y al script* * * * * /usr/bin/python3 /home/usuario/scripts/tarea.pySiempre redirige la salida a un log para poder investigar si algo sale mal:
# Sin log: si hay un error, nunca te enterarás0 3 * * * /home/usuario/scripts/respaldo.sh
# Con log: guardas la salida y los errores0 3 * * * /home/usuario/scripts/respaldo.sh >> /home/usuario/logs/respaldo.log 2>&1El 2>&1 al final significa “envía los errores al mismo lugar que la salida normal”. Así tanto los mensajes normales como los errores quedan guardados en el log.
Los 3 errores más comunes con cron
- Usar rutas relativas: Siempre usa rutas absolutas para scripts y programas.
- No dar permisos de ejecución: Tu script necesita
chmod +xpara que cron pueda ejecutarlo. - No redirigir la salida: Sin un log, no sabrás si tu tarea falló o qué error produjo.
Script de ejemplo para usar con Cron
Veamos un ejemplo completo de un script diseñado para ser ejecutado por cron:
#!/bin/bash
# Script de limpieza: elimina archivos temporales mayores a 7 días# Diseñado para ejecutarse con cron
LOG="$HOME/logs/limpieza.log"mkdir -p "$HOME/logs"DIR="/tmp"
echo "=== Limpieza $(date) ===" >> "$LOG"
# Encontrar y contar archivos viejosarchivos=$(find "$DIR" -type f -mtime +7 -name "*.tmp" 2>/dev/null)
if [ -n "$archivos" ]; then cantidad=$(echo "$archivos" | wc -l) echo "Encontrados $cantidad archivos para eliminar" >> "$LOG"
echo "$archivos" | while read -r f; do rm "$f" && echo " Eliminado: $f" >> "$LOG" doneelse echo "No hay archivos para limpiar" >> "$LOG"fi
echo "=== Fin ===" >> "$LOG"# Dar permisos de ejecuciónchmod +x limpieza.sh
# Agregar al crontab para ejecutar todos los días a las 3 AMcrontab -e# Agregar esta línea:# 0 3 * * * /home/usuario/scripts/limpieza.shVerificar que cron funciona
Si acabas de configurar una tarea cron y quieres verificar que funciona, sigue estos pasos:
# 1. Verificar que el servicio cron está corriendosystemctl status cron# Debería decir "active (running)"
# 2. Agregar una tarea de prueba que se ejecute cada minutocrontab -e# Agregar: * * * * * echo "$(date) - cron funciona" >> /tmp/cron-test.log
# 3. Esperar un minuto y verificarcat /tmp/cron-test.log# Deberías ver una línea con la fecha
# 4. ¡MUY IMPORTANTE! Eliminar la tarea de pruebacrontab -e# Borrar la línea de prueba (si la dejas, generará una línea por minuto para siempre)No olvides eliminar las tareas de prueba
Si dejas una tarea que se ejecuta cada minuto, generará datos indefinidamente. Un echo simple no es grave, pero un script que mueve archivos o consume recursos podría causar problemas. Siempre elimina tus tareas de prueba después de verificar.
Resumen
| Comando | Descripción |
|---|---|
| crontab -l | Ver tus tareas programadas actuales |
| crontab -e | Editar tus tareas programadas |
| crontab -r | Eliminar TODAS las tareas (cuidado) |
| systemctl status cron | Verificar que el servicio cron está activo |
Ejercicios del módulo
- Ejecuta
crontab -lpara ver si tienes alguna tarea programada. Si dice “no crontab for user”, es normal. - Ejecuta
systemctl status cronpara verificar que el servicio está corriendo. - Traduce estas expresiones cron a español (o verifica en crontab.guru):
0 12 * * *30 8 * * 1-50 0 1 * **/10 * * * *
- Escribe la expresión cron para: “todos los domingos a las 6 PM”.
- Escribe la expresión cron para: “cada 30 minutos, solo entre las 9 AM y las 6 PM, de lunes a viernes”.
- Crea una tarea cron de prueba que escriba la fecha actual en
/tmp/mi-cron.logcada minuto. Espera 2 minutos y verifica concat /tmp/mi-cron.log. Luego elimina la tarea de prueba. - Crea el script
limpieza.shdel ejemplo. Ejecútalo manualmente primero para verificar que funciona (./limpieza.sh). Luego agrégalo al crontab. - Desafío: Crea un script que registre el uso de disco (
df -h) en un archivo de log con fecha y hora, y prográmalo con cron para que se ejecute cada 6 horas.
Ejercicios prácticos finales
Llegaste al final del curso. Estos ejercicios integradores combinan todo lo que has aprendido en los módulos anteriores. Son más complejos que los ejercicios de cada módulo, porque requieren usar múltiples habilidades juntas.
Intenta resolver cada ejercicio por tu cuenta antes de ver la solución. Si te atascas, vuelve al módulo correspondiente para repasar. La práctica es la única forma de internalizar estos conocimientos.
Consejo antes de empezar
Crea una carpeta ejercicios-finales en tu home para trabajar sin ensuciar otros directorios: mkdir ~/ejercicios-finales && cd ~/ejercicios-finales.
Ejercicio 1: Organizador de archivos por extensión
Contexto: Imagina que tienes una carpeta de descargas llena de archivos mezclados: PDFs, imágenes, documentos, etc. Quieres organizarlos automáticamente en subcarpetas según su extensión.
Requisitos:
- El script recibe un directorio como argumento (o usa el actual por defecto).
- Verifica que el directorio existe antes de continuar.
- Crea una subcarpeta para cada extensión encontrada (txt, jpg, pdf, etc.).
- Mueve cada archivo a su carpeta correspondiente.
- Muestra un resumen de cuántos archivos movió.
Preparación (para tener archivos de prueba):
mkdir ~/ejercicios-finales/descargascd ~/ejercicios-finales/descargastouch informe.pdf datos.csv foto1.jpg foto2.jpg notas.txt resumen.pdf tabla.csv imagen.pngVer solución
#!/bin/bash
directorio="${1:-.}"
if [ ! -d "$directorio" ]; then echo "Error: '$directorio' no es un directorio válido" exit 1fi
cd "$directorio" || exit 1
total=0
for archivo in *.*; do # Verificar que es un archivo (no una carpeta) [ -f "$archivo" ] || continue
# Obtener la extensión extension="${archivo##*.}"
# Crear la carpeta para esa extensión mkdir -p "$extension"
# Mover el archivo mv "$archivo" "$extension/" echo "Movido: $archivo → $extension/" ((total++))done
echo ""echo "¡Organización completada! Se movieron $total archivos."chmod +x organizador.sh./organizador.sh ~/ejercicios-finales/descargasEjercicio 2: Monitor de sistema con reporte
Contexto: Necesitas un script que genere un reporte del estado de tu sistema, útil para enviar a alguien que te pregunte “¿cómo está el servidor?”.
Requisitos:
- Mostrar: usuario actual, hostname, sistema operativo, fecha y hora.
- Uso de disco del directorio home (en formato legible).
- Cantidad de procesos en ejecución.
- Memoria disponible (si el comando está disponible).
- Los 5 procesos que más CPU consumen.
- Guardar el reporte en un archivo con la fecha en el nombre.
Ver solución
#!/bin/bash
FECHA=$(date +%Y%m%d_%H%M%S)REPORTE="reporte_${FECHA}.txt"
{ echo "========================================" echo " REPORTE DEL SISTEMA" echo " Generado: $(date '+%Y-%m-%d %H:%M:%S')" echo "========================================" echo "" echo "--- Información general ---" echo "Usuario: $(whoami)" echo "Hostname: $(hostname)" echo "Sistema: $(uname -s -r)" echo "" echo "--- Uso de disco (home) ---" du -sh ~ 2>/dev/null echo "" echo "--- Espacio en disco ---" df -h / 2>/dev/null echo "" echo "--- Procesos activos ---" echo "Total: $(ps aux | wc -l) procesos" echo "" echo "--- Memoria ---" free -h 2>/dev/null || echo "(comando free no disponible)" echo "" echo "--- Top 5 procesos por CPU ---" ps aux --sort=-%cpu 2>/dev/null | head -6 echo "" echo "========================================"} | tee "$REPORTE"
echo ""echo "Reporte guardado en: $REPORTE"Ejercicio 3: Buscador de archivos grandes
Contexto: Tu disco se está llenando y necesitas encontrar qué archivos están ocupando más espacio. Este script te ayuda a identificarlos rápidamente.
Requisitos:
- Recibe un directorio y un tamaño mínimo como argumentos.
- Si no se proporcionan, usa valores por defecto razonables.
- Lista los archivos que superen ese tamaño, ordenados de mayor a menor.
- Muestra el tamaño en formato legible (MB, GB).
- Al final muestra el total de archivos encontrados y el espacio total que ocupan.
Ver solución
#!/bin/bash
directorio="${1:-.}"tamano_min="${2:-10M}"
if [ ! -d "$directorio" ]; then echo "Error: '$directorio' no es un directorio válido" echo "Uso: $0 [directorio] [tamaño-mínimo]" echo "Ejemplo: $0 /home/usuario 50M" exit 1fi
echo "Buscando archivos mayores a $tamano_min en $directorio..."echo ""
resultados=$(find "$directorio" -type f -size +$tamano_min -exec du -h {} + 2>/dev/null | sort -rh)
if [ -z "$resultados" ]; then echo "No se encontraron archivos mayores a $tamano_min"else echo "TAMAÑO ARCHIVO" echo "------ -------" echo "$resultados" echo "" total=$(echo "$resultados" | wc -l) echo "Total: $total archivos encontrados"fichmod +x archivos-grandes.sh./archivos-grandes.sh /home/usuario 50MEjercicio 4: Respaldo automatizado con rotación
Contexto: Necesitas un sistema de respaldo automático que se ejecute diariamente con cron, pero que no acumule respaldos infinitamente (o se llenará el disco).
Requisitos:
- Crea un respaldo comprimido (.tar.gz) de una carpeta específica.
- El nombre del archivo incluye la fecha de creación.
- Elimina automáticamente los respaldos de más de 30 días.
- Registra todo en un archivo de log.
- Incluye verificación de errores.
- Configurar en cron para ejecutar diariamente a las 2 AM.
Ver solución
#!/bin/bash
# Configuración (modifica estas rutas según tu sistema)ORIGEN="/home/usuario/proyectos"DESTINO="/home/usuario/respaldos"FECHA=$(date +%Y%m%d)ARCHIVO="respaldo_${FECHA}.tar.gz"LOG="/home/usuario/respaldos/respaldo.log"DIAS_RETENER=30
# Crear directorio de respaldo si no existemkdir -p "$DESTINO"
echo "$(date) - Iniciando respaldo..." >> "$LOG"
# Verificar que el directorio origen existeif [ ! -d "$ORIGEN" ]; then echo "$(date) - ERROR: '$ORIGEN' no existe" >> "$LOG" exit 1fi
# Crear respaldotar -czf "${DESTINO}/${ARCHIVO}" "$ORIGEN" 2>> "$LOG"
if [ $? -eq 0 ]; then tamano=$(du -h "${DESTINO}/${ARCHIVO}" | cut -f1) echo "$(date) - Respaldo creado: ${ARCHIVO} (${tamano})" >> "$LOG"else echo "$(date) - ERROR al crear respaldo" >> "$LOG" exit 1fi
# Eliminar respaldos antiguoseliminados=$(find "$DESTINO" -name "respaldo_*.tar.gz" -mtime +$DIAS_RETENER -delete -print 2>/dev/null)if [ -n "$eliminados" ]; then cantidad=$(echo "$eliminados" | wc -l) echo "$(date) - Eliminados $cantidad respaldos antiguos" >> "$LOG"fi
echo "$(date) - Respaldo completado exitosamente" >> "$LOG"echo "---" >> "$LOG"# Dar permisos y probar manualmente primerochmod +x auto-respaldo.sh./auto-respaldo.sh
# Si funciona bien, agregar al croncrontab -e# Agregar: 0 2 * * * /home/usuario/scripts/auto-respaldo.shEjercicio 5: Gestor de notas en terminal
Contexto: Quieres una forma rápida de tomar notas desde la terminal, sin abrir ningún otro programa. Este script te da un mini sistema de notas.
Requisitos:
- Menú interactivo con opciones: crear nota, listar notas, buscar en notas, ver una nota, eliminar nota.
- Las notas se guardan como archivos individuales en una carpeta dedicada.
- Cada nota tiene fecha de creación en el nombre del archivo.
- La búsqueda funciona por contenido (grep).
- Al eliminar, pide confirmación antes de borrar.
Ver solución
#!/bin/bash
DIRECTORIO="$HOME/mis-notas"mkdir -p "$DIRECTORIO"
crear_nota() { read -p "Título de la nota: " titulo
if [ -z "$titulo" ]; then echo "El título no puede estar vacío" return fi
# Convertir espacios a guiones para el nombre de archivo nombre=$(echo "$titulo" | tr ' ' '-' | tr '[:upper:]' '[:lower:]') fecha=$(date +%Y%m%d_%H%M%S) archivo="${DIRECTORIO}/${fecha}_${nombre}.txt"
echo "Escribe el contenido (termina con una línea vacía):" contenido="" while IFS= read -r linea; do [ -z "$linea" ] && break contenido="${contenido}${linea}\n" done
printf "# %s\n# Fecha: %s\n\n%b" "$titulo" "$(date)" "$contenido" > "$archivo" echo "" echo "Nota guardada: $(basename "$archivo")"}
listar_notas() { echo "" echo "=== TUS NOTAS ==="
archivos=$(ls "$DIRECTORIO"/*.txt 2>/dev/null) if [ -z "$archivos" ]; then echo "No hay notas todavía. Crea una con la opción 1." return fi
for nota in "$DIRECTORIO"/*.txt; do nombre=$(basename "$nota") titulo=$(head -1 "$nota" | sed 's/^# //') echo " - $nombre" echo " $titulo" done}
ver_nota() { listar_notas echo "" read -p "Nombre del archivo a ver: " archivo
if [ -f "$DIRECTORIO/$archivo" ]; then echo "" echo "---" cat "$DIRECTORIO/$archivo" echo "---" else echo "Archivo no encontrado." fi}
buscar_notas() { read -p "Buscar: " termino
if [ -z "$termino" ]; then echo "Ingresa un término de búsqueda" return fi
echo "" echo "Resultados para '$termino':" resultados=$(grep -rl "$termino" "$DIRECTORIO" 2>/dev/null)
if [ -z "$resultados" ]; then echo " No se encontraron coincidencias." return fi
echo "$resultados" | while read -r archivo; do echo " $(basename "$archivo"):" grep -n "$termino" "$archivo" | head -3 | sed 's/^/ /' done}
eliminar_nota() { listar_notas echo "" read -p "Nombre del archivo a eliminar: " archivo
if [ -f "$DIRECTORIO/$archivo" ]; then read -p "¿Estás seguro de eliminar '$archivo'? (s/n): " confirmar if [ "$confirmar" = "s" ]; then rm "$DIRECTORIO/$archivo" echo "Nota eliminada." else echo "Cancelado." fi else echo "Archivo no encontrado." fi}
# Menú principalecho "=== GESTOR DE NOTAS ==="echo "Directorio: $DIRECTORIO"
while true; do echo "" echo "-------------------" echo "1) Crear nota" echo "2) Listar notas" echo "3) Ver una nota" echo "4) Buscar en notas" echo "5) Eliminar nota" echo "6) Salir" read -p "Opción: " opcion
case $opcion in 1) crear_nota ;; 2) listar_notas ;; 3) ver_nota ;; 4) buscar_notas ;; 5) eliminar_nota ;; 6) echo "¡Hasta luego!"; exit 0 ;; *) echo "Opción no válida. Elige entre 1 y 6." ;; esacdoneEjercicio 6: Analizador de logs
Contexto: En ciencia de datos, frecuentemente necesitas analizar archivos de texto para extraer patrones. Este ejercicio simula el análisis de un archivo de log de un servidor web.
Requisitos:
- Primero, genera un archivo de log de ejemplo (se proporciona el comando).
- Crea un script que analice el log y muestre: total de líneas, cantidad de errores (ERROR), cantidad de advertencias (WARNING), las 5 líneas de error más recientes.
- Guarda el resumen en un archivo de reporte.
Preparación:
# Generar un log de ejemplofor i in {1..50}; do nivel=$((RANDOM % 3)) case $nivel in 0) echo "$(date -d "-$((RANDOM % 100)) minutes" '+%Y-%m-%d %H:%M:%S') [INFO] Operación completada correctamente" ;; 1) echo "$(date -d "-$((RANDOM % 100)) minutes" '+%Y-%m-%d %H:%M:%S') [WARNING] Uso de memoria alto: $((RANDOM % 50 + 50))%" ;; 2) echo "$(date -d "-$((RANDOM % 100)) minutes" '+%Y-%m-%d %H:%M:%S') [ERROR] Conexión rechazada desde 192.168.1.$((RANDOM % 255))" ;; esacdone > ejemplo.logVer solución
#!/bin/bash
archivo="${1:-ejemplo.log}"reporte="analisis_$(date +%Y%m%d_%H%M%S).txt"
if [ ! -f "$archivo" ]; then echo "Error: '$archivo' no existe" echo "Uso: $0 <archivo-de-log>" exit 1fi
{ echo "=== ANÁLISIS DE LOG ===" echo "Archivo: $archivo" echo "Fecha del análisis: $(date)" echo ""
total=$(wc -l < "$archivo") info=$(grep -c "\[INFO\]" "$archivo") warnings=$(grep -c "\[WARNING\]" "$archivo") errores=$(grep -c "\[ERROR\]" "$archivo")
echo "--- Resumen ---" echo "Total de líneas: $total" echo "INFO: $info" echo "WARNING: $warnings" echo "ERROR: $errores" echo ""
echo "--- Últimos 5 errores ---" grep "\[ERROR\]" "$archivo" | tail -5 echo ""
echo "--- Últimas 5 advertencias ---" grep "\[WARNING\]" "$archivo" | tail -5 echo ""
echo "========================"} | tee "$reporte"
echo ""echo "Reporte guardado en: $reporte"Ejercicio 7: Creador de proyectos
Contexto: Cada vez que empiezas un proyecto nuevo de ciencia de datos, necesitas crear la misma estructura de carpetas. Automatiza este proceso.
Requisitos:
- Recibe el nombre del proyecto como argumento.
- Crea una estructura estándar:
data/raw,data/processed,notebooks,scripts,output. - Crea archivos iniciales:
README.mdcon el nombre del proyecto,.gitignorecon patrones comunes, y un scriptsetup.shvacío. - Muestra la estructura creada con
tree(o confindsi tree no está instalado).
Ver solución
#!/bin/bash
nombre="${1}"
if [ -z "$nombre" ]; then read -p "Nombre del proyecto: " nombrefi
if [ -z "$nombre" ]; then echo "Error: necesitas proporcionar un nombre de proyecto" exit 1fi
if [ -d "$nombre" ]; then echo "Error: ya existe una carpeta llamada '$nombre'" exit 1fi
echo "Creando proyecto '$nombre'..."
# Crear estructura de directoriosmkdir -p "$nombre"/{data/{raw,processed},notebooks,scripts,output}
# Crear README.mdcat > "$nombre/README.md" << EOF# $nombre
Proyecto de ciencia de datos.
## Estructura
- \`data/raw/\` — Datos crudos (no modificar)- \`data/processed/\` — Datos procesados- \`notebooks/\` — Jupyter notebooks- \`scripts/\` — Scripts de procesamiento- \`output/\` — Resultados y gráficos
## Fecha de creación
$(date '+%Y-%m-%d')EOF
# Crear .gitignorecat > "$nombre/.gitignore" << EOF# Datos grandesdata/raw/*.csvdata/raw/*.xlsx*.zip
# Python__pycache__/*.pyc.venv/
# Jupyter.ipynb_checkpoints/
# Sistema.DS_StoreThumbs.db
# Outputoutput/*.pngoutput/*.pdfEOF
# Crear script inicialcat > "$nombre/scripts/setup.sh" << EOF#!/bin/bashecho "Configurando entorno para $nombre..."# Agrega aquí los comandos de configuraciónEOFchmod +x "$nombre/scripts/setup.sh"
# Mostrar resultadoecho ""echo "Proyecto creado exitosamente:"if command -v tree &>/dev/null; then tree "$nombre"else find "$nombre" -type f -o -type d | sortfi¿Qué sigue después?
Si completaste estos ejercicios, tienes una base sólida en terminal y Bash. Los siguientes pasos naturales en tu camino de ciencia de datos son:
- Git: Control de versiones para tus proyectos. Se usa enteramente desde la terminal.
- SSH: Conectarte a servidores remotos para procesar datos.
- Docker: Contenedores para reproducir entornos de análisis.
- Python/R desde la terminal: Ejecutar scripts de análisis directamente.
Recuerda que este curso forma parte del programa de Hazla con Datos. Sigue aprendiendo con los otros cursos del programa.