Comandos Bash
Puedo darte una lista muy amplia y bien organizada de los comandos Bash más importantes, con explicaciones técnicas claras. Pero hay un detalle importante: no existe una “lista completa” absoluta, porque Bash puede ejecutar:
- Comandos internos (builtins)
- Comandos externos del sistema (GNU coreutils, utilidades POSIX, etc.)
- Comandos instalados por paquetes adicionales
- Alias y funciones definidas por el usuario
Aun así, puedo darte la lista más exhaustiva y útil, cubriendo:
- Builtins de Bash
- Comandos esenciales de GNU/Linux
- Utilidades POSIX estándar
- Comandos avanzados de administración del sistema
Voy a estructurarlo para que sea técnico, claro y práctico.
🧠 1. Builtins de Bash (comandos internos)
Estos comandos los ejecuta el propio intérprete Bash, sin llamar a programas externos.
🔧 Gestión del entorno y shell
| Comando | Explicación técnica |
|---|---|
cd | Cambia el directorio actual modificando la variable interna PWD. |
pwd | Muestra el directorio actual leyendo PWD o consultando el sistema de archivos. |
echo | Imprime texto en stdout; interpreta escapes si se usa -e. |
export | Marca variables para ser heredadas por procesos hijos mediante el entorno. |
set | Configura flags del shell y lista variables internas. |
unset | Elimina variables o funciones del entorno del shell. |
alias | Crea alias que se expanden antes de ejecutar el comando. |
unalias | Elimina alias definidos. |
type | Indica si un comando es builtin, alias, función o binario. |
source / . | Ejecuta un script en el contexto del shell actual sin crear subshell. |
🧵 Control de procesos
| Comando | Explicación técnica |
|---|---|
jobs | Lista procesos en background gestionados por el shell. |
fg | Trae un job al foreground. |
bg | Reanuda un job en background. |
kill | Envía señales POSIX a procesos (SIGTERM, SIGKILL, etc.). |
wait | Espera a que un proceso hijo termine y devuelve su exit code. |
📚 Estructuras de control
| Comando | Explicación técnica |
|---|---|
if, then, else, elif | Estructuras condicionales basadas en exit codes. |
for, while, until | Bucles iterativos. |
case | Selección múltiple basada en patrones. |
function | Define funciones internas del shell. |
📁 Manipulación de archivos (interno)
| Comando | Explicación técnica |
|---|---|
test / [ | Evalúa expresiones lógicas y de archivos. |
read | Lee entrada desde stdin y asigna a variables. |
printf | Imprime texto con formato POSIX. |
📦 2. Comandos esenciales del sistema (GNU coreutils)
Estos son binarios externos ubicados normalmente en /bin o /usr/bin.
📁 Gestión de archivos y directorios
| Comando | Explicación técnica |
|---|---|
ls | Lista entradas de un directorio leyendo inodos. |
cp | Copia archivos usando syscalls read() y write(). |
mv | Mueve archivos; si es en el mismo FS usa rename(). |
rm | Elimina entradas del directorio; no borra datos, solo inodos. |
mkdir | Crea directorios usando mkdir() syscall. |
rmdir | Elimina directorios vacíos. |
touch | Actualiza timestamps o crea archivos vacíos. |
ln | Crea enlaces duros o simbólicos. |
📄 Visualización de contenido
| Comando | Explicación técnica |
|---|---|
cat | Concatena archivos a stdout. |
less | Paginador interactivo eficiente. |
head | Muestra primeras líneas. |
tail | Muestra últimas líneas; con -f sigue cambios en tiempo real. |
🔍 Búsqueda
| Comando | Explicación técnica |
|---|---|
grep | Filtra texto usando expresiones regulares. |
find | Recorrido recursivo del FS evaluando predicados. |
locate | Busca en una base de datos indexada (mlocate.db). |
🧮 Procesamiento de texto
| Comando | Explicación técnica |
|---|---|
awk | Lenguaje de procesamiento de texto basado en patrones y acciones. |
sed | Editor de flujo para sustituciones y transformaciones. |
cut | Extrae columnas por delimitador. |
sort | Ordena líneas usando algoritmos eficientes (merge sort). |
uniq | Elimina duplicados consecutivos. |
tr | Traduce o elimina caracteres. |
⚙️ 3. Administración del sistema
| Comando | Explicación técnica |
|---|---|
ps | Lista procesos leyendo /proc. |
top / htop | Monitor interactivo de procesos. |
df | Muestra uso de discos leyendo superblocks. |
du | Calcula tamaño de directorios recursivamente. |
free | Muestra memoria del sistema. |
uname | Información del kernel. |
systemctl | Controla servicios systemd. |
journalctl | Lee logs binarios de systemd. |
🌐 4. Red y comunicaciones
| Comando | Explicación técnica |
|---|---|
ping | Envía ICMP echo requests. |
curl | Cliente HTTP/FTP; usa libcurl. |
wget | Descarga archivos vía HTTP/HTTPS/FTP. |
ssh | Conexión remota cifrada usando OpenSSH. |
scp | Copia archivos sobre SSH. |
netstat / ss | Muestra sockets y conexiones. |
ip | Configura interfaces, rutas y reglas de red. |
🧩 5. Compresión y empaquetado
| Comando | Explicación técnica |
|---|---|
tar | Empaqueta archivos sin comprimir. |
gzip / gunzip | Compresión DEFLATE. |
zip / unzip | Formato ZIP. |
xz | Compresión LZMA2. |
Versión extendida de builtins y tabla completa de coreutils
Vamos a construir la referencia más completa y útil que puedes tener en una sola pieza:
- Todos los builtins de Bash, con una descripción técnica clara.
- La tabla completa de GNU coreutils, organizada por categorías.
Todo en formato limpio, consultable y sin ruido.
🧠 1. Builtins de Bash (lista extendida y completa)
Esta es la lista oficial de builtins que Bash incorpora internamente. Incluye todos los builtins POSIX + los específicos de Bash.
🔧 Gestión del entorno y variables
| Builtin | Descripción técnica |
|---|---|
alias | Define alias que se expanden antes del análisis sintáctico. |
unalias | Elimina alias del entorno del shell. |
bind | Gestiona bindings de teclado de readline. |
declare / typeset | Declara variables con atributos (integer, array, readonly…). |
export | Marca variables para ser heredadas por procesos hijos. |
readonly | Marca variables como inmutables. |
set | Configura flags del shell y lista variables. |
unset | Elimina variables o funciones del entorno. |
local | Declara variables locales dentro de funciones. |
let | Evalúa expresiones aritméticas en el contexto del shell. |
printf | Imprime texto con formato POSIX. |
eval | Ejecuta una cadena tras expandirla completamente. |
📁 Navegación y manipulación del entorno
| Builtin | Descripción técnica |
|---|---|
cd | Cambia el directorio actual modificando PWD y OLDPWD. |
pwd | Muestra el directorio actual (interno o consultando el FS). |
dirs | Muestra el stack de directorios. |
pushd | Añade un directorio al stack y cambia a él. |
popd | Extrae un directorio del stack y cambia a él. |
🧵 Control de procesos y jobs
| Builtin | Descripción técnica |
|---|---|
jobs | Lista procesos gestionados por el shell. |
fg | Trae un job al foreground. |
bg | Reanuda un job en background. |
kill | Envía señales POSIX a procesos. |
wait | Espera a que un proceso hijo termine. |
disown | Elimina un job del control del shell. |
suspend | Suspende el shell enviando SIGSTOP. |
🧩 Ejecución y control del flujo
| Builtin | Descripción técnica |
|---|---|
. / source | Ejecuta un script en el contexto del shell actual. |
exec | Reemplaza el proceso actual por otro (sin fork). |
exit | Termina el shell con un exit code. |
return | Devuelve un exit code desde una función. |
shift | Desplaza los parámetros posicionales. |
getopts | Analiza opciones estilo POSIX. |
📚 Entrada y salida
| Builtin | Descripción técnica |
|---|---|
echo | Imprime texto en stdout. |
read | Lee entrada desde stdin y asigna a variables. |
mapfile / readarray | Lee líneas en un array. |
🧮 Aritmética
| Builtin | Descripción técnica |
|---|---|
(( )) | Evaluación aritmética nativa del shell. |
let | Evaluación aritmética tradicional. |
🧱 Estructuras de control (palabras reservadas)
Estas no son builtins, pero forman parte del lenguaje Bash:
if, then, else, elif, fi, for, while, until, do, done, case, esac, select, function, time, coproc, !, {}, [[ ]].
📦 2. Tabla completa de GNU coreutils
GNU coreutils contiene 106 comandos. Los organizo por categoría para que sea realmente útil.
📁 A. Gestión de archivos y directorios
| Comando |
|---|
basename |
chcon |
chgrp |
chmod |
chown |
cp |
dd |
df |
dir |
dircolors |
install |
ln |
ls |
mkdir |
mkfifo |
mknod |
mktemp |
mv |
readlink |
realpath |
rm |
rmdir |
shred |
sync |
touch |
truncate |
vdir |
📄 B. Visualización y lectura de archivos
| Comando |
|---|
cat |
tac |
nl |
od |
base32 |
base64 |
fmt |
fold |
head |
tail |
split |
csplit |
sum |
🔍 C. Búsqueda y comparación
| Comando |
|---|
cmp |
comm |
diff |
dircmp |
md5sum |
sha1sum |
sha224sum |
sha256sum |
sha384sum |
sha512sum |
cksum |
🧮 D. Procesamiento de texto
| Comando |
|---|
cut |
expand |
unexpand |
join |
paste |
sort |
uniq |
tr |
wc |
🧩 E. Utilidades del sistema
| Comando |
|---|
arch |
date |
df |
env |
expr |
factor |
groups |
hostid |
id |
logname |
nice |
nohup |
nproc |
pathchk |
pinky |
printenv |
printf |
pwd |
seq |
sleep |
stat |
stdbuf |
stty |
tee |
test |
timeout |
tty |
uname |
uptime |
users |
who |
whoami |
yes |
🔐 F. Permisos y atributos
| Comando |
|---|
chcon |
chgrp |
chmod |
chown |
runcon |
🧱 G. Utilidades de shell
| Comando |
|---|
false |
true |
echo |
printf |
Comandos menos conocidos
🧩 1. Gestión de entorno y variables
🔧 1.1. bind — gestionar atajos de teclado de Readline
Bash usa Readline para leer lo que escribes en el prompt. Readline permite:
- Atajos tipo Emacs (Ctrl+A, Ctrl+E…)
- Atajos tipo Vi
- Macros de teclado
- Reasignar teclas
bind sirve para ver, modificar o crear atajos.
Ver todos los atajos actuales
Código
bind -P
Asignar un atajo nuevo
Ejemplo: que F2 inserte la palabra “hola”:
Código
bind '"\eOQ": "hola"'
Cambiar a modo vi
Código
set -o vi
🔧 1.2. declare / typeset — variables con atributos
Son equivalentes en Bash. Sirven para declarar variables con tipos o atributos especiales.
Atributos importantes
| Atributo | Significado |
|---|---|
-i | Variable entera (evalúa expresiones) |
-a | Array indexado |
-A | Array asociativo |
-r | Solo lectura |
-x | Exportar al entorno |
Ejemplos
Variable entera
Código
declare -i x=5+3
echo $x # 8
Array
Código
declare -a nums=(1 2 3)
Array asociativo
Código
declare -A persona=([nombre]=David [edad]=40)
Solo lectura
Código
declare -r PI=3.14159
🔧 1.3. eval — ejecutar código generado dinámicamente
eval vuelve a interpretar una cadena como código Bash.
Ejemplo básico
Código
cmd="ls -l"
eval $cmd
Ejemplo potente: variables dinámicas
Código
var="nombre"
eval $var="David"
echo $nombre
Riesgo
Si evalúas texto no controlado → inyección de comandos.
🧭 2. Navegación y manipulación del entorno
🔧 2.1. pushd y popd — pila de directorios
Bash mantiene una pila de directorios.
pushd — cambia de directorio y lo mete en la pila
Código
pushd /etc
popd — vuelve al directorio anterior
Código
popd
Ver la pila
Código
dirs -v
Esto es oro para navegar rápido entre 2–3 rutas.
🧵 3. Control de procesos y jobs
🔧 3.1. jobs — lista procesos en background
Código
sleep 100 &
jobs
🔧 3.2. fg — trae un job al foreground
Código
fg %1
🔧 3.3. bg — reanuda un job en background
Código
bg %1
🔧 3.4. kill — envía señales
Código
kill -9 1234
kill -TERM %1
🔧 3.5. wait — espera a que un proceso termine
Código
wait %1
🔧 3.6. disown — elimina un job del control del shell
Código
disown %1
El proceso sigue, pero el shell ya no lo controla.
🔧 3.7. suspend — suspende el shell
Código
suspend
⚙️ 4. Ejecución y control de flujo
🔧 4.1. exec — reemplaza el proceso actual
Ejemplo: redirigir todo el shell a un archivo:
Código
exec > salida.log
Ejemplo: reemplazar el shell por otro programa:
Código
exec ls
El shell desaparece.
🔧 4.2. shift — desplaza parámetros posicionales
Código
set -- a b c d
echo $1 # a
shift
echo $1 # b
Muy útil en scripts con argumentos.
🔧 4.3. getopts — parseo POSIX de opciones
Ejemplo:
Código
while getopts "ab:c" opt; do
case $opt in
a) echo "Opción -a" ;;
b) echo "Opción -b con valor $OPTARG" ;;
c) echo "Opción -c" ;;
esac
done
📥 5. Entrada y salida
🔧 5.1. mapfile / readarray — leer líneas en un array
Son idénticos.
Código
mapfile arr < archivo.txt
echo "${arr[0]}"
Con numeración automática.
➗ 6. Aritmética
🔧 6.1. (( )) — aritmética nativa del shell
Código
((x = 5 + 3))
echo $x
Permite comparaciones:
Código
if (( x > 10 )); then ...
🔧 6.2. let — versión antigua
Código
let x=5+3
🔧 6.3. bc — calculadora arbitraria de precisión
Código
echo "scale=5; 10/3" | bc
Funciones, bucles, variables… Es un mini lenguaje matemático.
🧱 7. Estructuras de control
🔧 7.1. coproc — ejecutar un proceso con pipes automáticos
Ejemplo:
Código
coproc DATE { date; }
read linea <&"${DATE[0]}"
echo "La fecha es: $linea"
Crea un proceso con dos pipes listos para usar.
🔧 7.2. ! — negación lógica
Código
if ! grep -q error log.txt; then
echo "No hay errores"
fi
Nada que ver con el history.
📁 8. Gestión de archivos y directorios
🔧 8.1. basename — extraer nombre de archivo
Código
basename /usr/local/bin/python
# python
🔧 8.2. chgrp — cambiar grupo
Código
chgrp staff archivo
🔧 8.3. chown — cambiar propietario
Código
chown david archivo
chown david:staff archivo
🔧 8.4. dd — copiar datos a bajo nivel
Código
dd if=/dev/zero of=archivo bs=1M count=10
Sirve para:
- Crear imágenes
- Copiar discos
- Convertir formatos
🔧 8.5. mkfifo — crear FIFO (named pipe)
Código
mkfifo canal
echo hola > canal
cat canal
🔧 8.6. mknod — crear nodos de dispositivo
Solo para administradores avanzados.
🔧 8.7. mktemp — crear archivo temporal seguro
Código
mktemp
🔧 8.8. readlink — resolver enlaces simbólicos
Código
readlink -f /usr/bin/python
🔧 8.9. shred — sobrescribir archivo para borrado seguro
Código
shred -u archivo
🔧 8.10. truncate — cambiar tamaño de archivo
Código
truncate -s 0 archivo
🔧 8.11. vdir — como ls -l
Código
vdir
📄 9. Visualización
🔧 9.1. tac — cat al revés
Código
tac archivo
🔧 9.2. nl — numerar líneas
Código
nl archivo
🔧 9.3. od — volcado hexadecimal
Código
od -x archivo
🔧 9.4. base32 / base64
Código
echo hola | base64
🔧 9.5. fmt — formatear párrafos
Código
fmt -w 40 archivo
🔧 9.6. fold — cortar líneas largas
Código
fold -w 20 archivo
🔧 9.7. split — dividir archivos
Código
split -b 1M archivo parte_
🔧 9.8. csplit — dividir por patrones
Código
csplit archivo '/ERROR/' '{*}'
🔧 9.9. sum — checksum antiguo
Código
sum archivo
🔍 10. Búsqueda y comparación
🔧 10.1. cmp — comparar binarios
Código
cmp a.bin b.bin
🔧 10.2. comm — comparar listas ordenadas
Código
comm lista1 lista2
🔧 10.3. dircmp — comparar directorios
Código
dircmp dir1 dir2
🔧 10.4. md5sum — hash MD5
Código
md5sum archivo
🔧 10.5. cksum — checksum CRC32
Código
cksum archivo
⚙️ 11. Utilidades del sistema
arch — arquitectura
Código
arch
expr — expresiones aritméticas
Código
expr 5 + 3
factor — descomposición en factores
Código
factor 360
hostid — ID del host
Código
hostid
nice — cambiar prioridad
Código
nice -n 10 comando
nproc — núcleos disponibles
Código
nproc
pathchk — comprobar validez de rutas
Código
pathchk /ruta/larga
pinky — versión reducida de finger
Código
pinky
stdbuf — cambiar buffers de E/S
Código
stdbuf -oL comando
stty — configurar terminal
Código
stty -a
tty — mostrar terminal actual
Código
tty
yes — repetir una cadena infinitamente
Código
yes hola
🔐 12. Permisos y atributos
chcon — cambiar contexto SELinux
Código
chcon -t httpd_sys_content_t archivo
runcon — ejecutar con contexto SELinux
Código
runcon -t httpd_t comando
Procesamiento de texto: awk, sed, cut, sort, uniq y tr
Vamos a hacer la guía definitiva, técnica y profunda, de los seis comandos de procesamiento de texto más importantes en Unix: awk, sed, cut, sort, uniq y tr. Cada uno con:
- Qué hace realmente a nivel técnico
- Cómo funciona internamente
- Sintaxis esencial
- Ejemplos prácticos
- Casos avanzados
- Errores típicos y cómo evitarlos
Todo pensado para alguien con tu perfil técnico.
🧠 1. AWK — El lenguaje de procesamiento de texto más potente en Unix
🧩 ¿Qué es AWK realmente?
AWK no es un comando, sino un lenguaje de programación completo diseñado para:
- Procesar texto línea a línea
- Dividir en campos automáticamente
- Aplicar patrones y acciones
- Trabajar con expresiones regulares
- Generar informes y transformaciones complejas
Internamente, AWK:
- Lee una línea
- La divide en campos usando el separador
FS - Evalúa patrones
- Ejecuta acciones
{ ... } - Imprime si procede
🧬 Sintaxis general
Código
awk 'patrón { acción }' archivo
🔧 Ejemplos esenciales
1) Imprimir la primera columna
Código
awk '{print $1}' datos.txt
2) Filtrar líneas que contengan “error”
Código
awk '/error/'
3) Sumar la tercera columna
Código
awk '{s += $3} END {print s}'
4) Cambiar separador de campos
Código
awk -F',' '{print $2}'
5) Reemplazar texto (más potente que sed)
Código
awk '{gsub("foo","bar"); print}'
🚀 Ejemplo avanzado: procesar logs
Código
awk '$9 == 404 {count[$1]++} END {for (ip in count) print ip, count[ip]}'
Cuenta cuántos errores 404 genera cada IP.
🧠 2. SED — Editor de flujo (stream editor)
🧩 ¿Qué hace realmente sed?
SED procesa texto sin cargarlo entero en memoria. Funciona línea a línea, aplicando transformaciones declarativas.
Internamente:
- Lee una línea
- La coloca en el pattern space
- Aplica comandos
- Imprime (a menos que uses
-n)
🔧 Sintaxis básica
Código
sed 'comando' archivo
🔧 Ejemplos esenciales
1) Sustitución simple
Código
sed 's/foo/bar/' archivo
2) Sustitución global
Código
sed 's/foo/bar/g'
3) Eliminar líneas que coincidan
Código
sed '/error/d'
4) Reemplazar solo en líneas que cumplan un patrón
Código
sed '/^#/{s/todo/nada/}'
5) Editar un archivo en sitio
Código
sed -i 's/foo/bar/g' archivo
🚀 Ejemplo avanzado: eliminar líneas entre dos patrones
Código
sed '/BEGIN/,/END/d'
🧠 3. CUT — Extracción de columnas o rangos
🧩 ¿Qué hace realmente cut?
CUT no interpreta expresiones regulares. Es extremadamente rápido porque:
- Trabaja por posiciones o delimitadores
- No analiza sintaxis compleja
- No reordena datos
🔧 Sintaxis
Código
cut -d',' -f2 archivo
🔧 Ejemplos esenciales
1) Extraer la segunda columna
Código
cut -f2
2) Usar delimitador personalizado
Código
cut -d':' -f1 /etc/passwd
3) Extraer rangos de caracteres
Código
cut -c1-10 archivo
🚀 Ejemplo avanzado: extraer múltiples columnas
Código
cut -d',' -f1,4,7 datos.csv
🧠 4. SORT — Ordenación eficiente de texto
🧩 ¿Qué hace realmente sort?
SORT usa algoritmos de ordenación externos (merge sort) optimizados para:
- Archivos enormes
- Ordenación por claves
- Ordenación numérica
- Ordenación por campos
Internamente:
- Divide en bloques
- Ordena cada bloque
- Hace merge de los bloques
🔧 Sintaxis
Código
sort [opciones] archivo
🔧 Ejemplos esenciales
1) Ordenar alfabéticamente
Código
sort archivo
2) Ordenar numéricamente
Código
sort -n archivo
3) Ordenar por la tercera columna
Código
sort -k3 archivo
4) Ordenar por columna numérica
Código
sort -k2,2n archivo
🚀 Ejemplo avanzado: ordenar por fecha (ISO 8601)
Código
sort -k1,1 archivo.log
🧠 5. UNIQ — Elimina duplicados consecutivos
🧩 ¿Qué hace realmente uniq?
UNIQ no detecta duplicados globales, solo consecutivos. Por eso suele usarse con sort.
Internamente:
- Compara línea actual con la anterior
- Si son iguales → descarta
- Si cambian → imprime
🔧 Sintaxis
Código
uniq archivo
🔧 Ejemplos esenciales
1) Eliminar duplicados consecutivos
Código
uniq
2) Contar ocurrencias
Código
uniq -c
3) Mostrar solo duplicados
Código
uniq -d
🚀 Ejemplo avanzado: top de palabras repetidas
Código
sort palabras.txt | uniq -c | sort -nr | head
🧠 6. TR — Traducción y eliminación de caracteres
🧩 ¿Qué hace realmente tr?
TR trabaja carácter a carácter, no por líneas. Es extremadamente rápido porque:
- No usa expresiones regulares
- No entiende campos
- Solo transforma bytes
🔧 Sintaxis
Código
tr SET1 SET2
🔧 Ejemplos esenciales
1) Convertir minúsculas a mayúsculas
Código
tr 'a-z' 'A-Z'
2) Eliminar caracteres
Código
tr -d 'aeiou'
3) Comprimir repeticiones
Código
tr -s ' '
4) Sustituir separadores
Código
tr ':' '\t'
🚀 Ejemplo avanzado: normalizar texto
Código
tr -cd '[:alnum:]\n'
Elimina todo excepto letras, números y saltos de línea.
Conceptos en bash: builtins, gnu coreutils, stat, posix o estandar posix, fork
Vamos a desmenuzar estos conceptos con precisión técnica, pero de forma clara y útil para tu nivel. Son piezas fundamentales para entender cómo funciona realmente un sistema Unix/Linux por dentro.
🧩 1. Builtins (comandos internos del shell)
🔧 ¿Qué son?
Un builtin es un comando que no es un programa externo, sino una función interna del propio intérprete de comandos (Bash, Zsh, etc.).
Ejemplos: cd, echo, export, alias, read.
🧠 ¿Por qué existen?
Porque hay operaciones que no pueden ejecutarse en un proceso hijo. Ejemplo clásico:
Código
cd /tmp
Si cd fuera un programa externo:
- El shell lanzaría un proceso hijo
- El hijo cambiaría de directorio
- El hijo terminaría
- El shell seguiría en el mismo directorio de antes
Por eso cd debe ejecutarse dentro del proceso del shell.
⚙️ Características técnicas
- Se ejecutan sin
fork() - Son más rápidos que los binarios externos
- Tienen acceso directo al estado interno del shell (variables, entorno, directorio actual)
📦 2. GNU coreutils
🔧 ¿Qué son?
Es un conjunto de programas esenciales para cualquier sistema GNU/Linux. Incluye comandos como:
ls,cp,mv,rmcat,head,tailsort,uniq,cutchmod,chown,stat
Son binarios externos, normalmente ubicados en:
Código
/usr/bin
/bin
🧠 ¿Por qué existen?
Porque implementan las herramientas básicas del sistema operativo siguiendo estándares POSIX, pero con extensiones GNU.
⚙️ Características técnicas
- Se ejecutan como procesos independientes
- Requieren
fork()+execve() - Son portables entre distribuciones Linux
- Suelen ser más potentes que las versiones POSIX puras
📏 3. POSIX (o estándar POSIX)
🔧 ¿Qué es POSIX?
POSIX = Portable Operating System Interface Es un estándar internacional que define:
- Cómo deben comportarse los comandos básicos
- Cómo deben funcionar las llamadas al sistema
- Cómo debe ser la API de procesos, señales, archivos, etc.
- Cómo debe comportarse un shell compatible
POSIX no es software. Es un conjunto de reglas que los sistemas Unix-like deben cumplir.
🧠 ¿Por qué existe?
Para que un script o programa funcione igual en:
- Linux
- macOS
- BSD
- Solaris
- AIX
⚙️ Ejemplo práctico
POSIX define que:
Código
ls
debe listar archivos, pero no define colores. Por eso:
lsen GNU tiene coloreslsen macOS no- Ambos siguen siendo POSIX
📊 4. stat (concepto general y comando)
🔧 ¿Qué es stat?
Hay dos cosas distintas:
1) La syscall stat() del kernel
Es una llamada al sistema que devuelve metadatos de un archivo, como:
- tamaño
- permisos
- inodo
- timestamps
- propietario
- tipo de archivo
Ejemplo en C:
c
struct stat info;
stat("archivo.txt", &info);
2) El comando stat de coreutils
Es un binario que muestra la información de la syscall stat() de forma legible.
Ejemplo:
Código
stat archivo.txt
Salida típica:
Código
Size: 2048 Blocks: 8 IO Block: 4096 regular file
Device: 803h/2051d Inode: 1234567 Links: 1
Access: (0644/-rw-r--r--) Uid: 1000 Gid: 1000
Access: 2024-01-01 12:00:00
Modify: 2024-01-01 12:00:00
Change: 2024-01-01 12:00:00
🧬 5. fork() — La base de la multitarea en Unix
🔧 ¿Qué es fork()?
fork() es una llamada al sistema que crea un nuevo proceso duplicando el proceso actual.
- El proceso original = padre
- El proceso duplicado = hijo
Ambos continúan ejecutándose desde el mismo punto del código.
🧠 ¿Por qué es tan importante?
Porque todos los comandos externos se ejecutan así:
- El shell llama a
fork() - El hijo ejecuta
execve()para cargar el binario - El padre espera o sigue ejecutando
Ejemplo conceptual:
Código
bash
└── fork()
└── execve("/usr/bin/ls")
⚙️ Características técnicas
- Copia el espacio de memoria del proceso (copy-on-write)
- Copia descriptores de archivo
- Copia variables de entorno
- El hijo tiene un PID distinto
🚀 Ejemplo en C
c
pid_t pid = fork();
if (pid == 0) {
printf("Soy el hijo\n");
} else {
printf("Soy el padre\n");
}
🎯 Resumen rápido
| Concepto | Qué es | Nivel |
|---|---|---|
| Builtins | Comandos internos del shell | Shell |
| GNU coreutils | Conjunto de binarios esenciales | Sistema |
| POSIX | Estándar que define cómo deben comportarse los sistemas Unix | Norma |
| stat | Syscall para obtener metadatos de archivos (y comando que la muestra) | Kernel / Usuario |
| fork() | Syscall que crea procesos | Kernel |
Este es uno de esos temas donde entender cómo funciona Unix por dentro te cambia la forma de ver cualquier shell o proceso. Te lo explico con rigor técnico, pero de forma clara.
🧩 1. ¿Por qué escribimos fork(), execve(), wait() con paréntesis?
Porque son funciones reales del sistema, no comandos del shell.
fork()execve()wait()kill()signal()
Todas ellas son llamadas al sistema (syscalls) expuestas a través de la biblioteca estándar de C (glibc en Linux).
🔧 ¿Qué significa esto?
En C, las syscalls se invocan como funciones:
c
pid_t pid = fork();
execve("/bin/ls", args, envp);
wait(&status);
Por eso se escriben con paréntesis: son funciones que reciben parámetros y devuelven valores.
🔬 ¿Qué ocurre realmente?
Aunque parecen funciones normales, en realidad:
- La función de C prepara los argumentos
- Ejecuta la instrucción
syscall(oint 0x80en sistemas antiguos) - El kernel toma el control
- Realiza la operación
- Devuelve al proceso
🧬 2. Cómo se relacionan fork(), execve(), wait() y signals
Este es el ciclo vital de cualquier comando externo que ejecutas en Bash, Zsh, etc.
Vamos paso a paso.
🧩 2.1 fork() — Crear un proceso hijo
fork() duplica el proceso actual:
- El padre sigue ejecutándose
- El hijo es una copia casi idéntica (copy-on-write)
- Ambos continúan desde la misma línea de código
El hijo recibe pid = 0 El padre recibe pid = <PID del hijo>
🧩 2.2 execve() — Reemplazar el proceso por un programa
Después de fork(), el hijo llama a execve():
c
execve("/usr/bin/ls", args, envp);
Esto:
- Descarta el código del proceso hijo
- Carga el binario solicitado
- Comienza a ejecutarlo desde su
main()
El PID no cambia. Solo cambia el contenido del proceso.
🧩 2.3 wait() — El padre espera al hijo
El shell (padre) ejecuta:
c
wait(&status);
Esto:
- Suspende al padre hasta que el hijo termine
- Recoge el exit code
- Evita procesos zombis
🧩 2.4 signals — Comunicación asíncrona
Las señales son interrupciones software:
SIGINT(Ctrl+C)SIGTERMSIGKILLSIGCHLD(cuando un hijo termina)SIGHUP
El shell usa señales para:
- Cancelar procesos
- Notificar terminación
- Controlar jobs en background
🧠 Resumen visual del ciclo
Código
shell
├── fork() → crea hijo
│
├── hijo → execve("/bin/ls")
│
└── padre → wait() hasta que hijo termine
🐚 3. Diferencias entre POSIX sh, Bash, Zsh, Dash y Fish
Aquí viene lo bueno. Cada shell tiene su filosofía, su velocidad y su compatibilidad.
📏 3.1 POSIX sh (Bourne Shell estándar)
✔️ Características
- Especificado por POSIX
- Sintaxis mínima y estable
- Máxima portabilidad
- Sin arrays, sin funciones avanzadas, sin extensiones
✔️ ¿Cuándo usarlo?
- Scripts que deben funcionar en cualquier Unix
- Entornos embebidos
- Init scripts
❌ Limitaciones
- Muy limitado comparado con Bash o Zsh
- No tiene sintaxis moderna
🟦 3.2 Bash — Bourne Again Shell
✔️ Características
- El shell más usado en Linux
- Compatible con POSIX sh
- Arrays, diccionarios, brace expansion, process substitution
- Funciones avanzadas
[[ ]]test mejoradocoproc,mapfile,readarray
✔️ Ventajas
- Potente y muy documentado
- Ideal para scripting serio
❌ Desventajas
- Más lento que Dash
- No es POSIX puro (tiene extensiones)
⭐ 3.3 Zsh — El shell más avanzado para usuarios
✔️ Características
- Autocompletado espectacular
- Globbing avanzado
- Arrays potentes
- Plugins (Oh My Zsh)
- Prompt extremadamente configurable
✔️ Ventajas
- El mejor shell interactivo
- Muy rápido en autocompletado
❌ Desventajas
- No es POSIX
- Scripts Zsh no son portables
⚡ 3.4 Dash — Debian Almquist Shell
✔️ Características
- Implementación minimalista de POSIX sh
- Ultra rápido
- Usado como
/bin/shen Debian/Ubuntu
✔️ Ventajas
- Ideal para scripts del sistema
- Arranca muy rápido
❌ Desventajas
- No tiene extensiones de Bash
- No sirve para scripting avanzado
🐟 3.5 Fish — Friendly Interactive Shell
✔️ Características
- No es POSIX
- Sintaxis propia
- Autocompletado inteligente
- Colores y sugerencias tipo IDE
- Arrays nativos
- Configuración web
✔️ Ventajas
- El mejor shell para principiantes
- Interactivo, moderno, cómodo
❌ Desventajas
- No sirve para scripting POSIX
- Sintaxis incompatible con Bash/Zsh
🧠 Resumen comparativo
| Shell | POSIX | Velocidad | Interactivo | Scripting | Extensiones |
|---|---|---|---|---|---|
| sh | ✔️ | ⚡⚡⚡ | ❌ | ✔️ | ❌ |
| bash | ✔️ (parcial) | ⚡ | ✔️ | ✔️✔️✔️ | ✔️ |
| zsh | ❌ | ⚡ | ⭐⭐⭐⭐⭐ | ✔️✔️ | ⭐⭐⭐⭐⭐ |
| dash | ✔️ | ⚡⚡⚡⚡⚡ | ❌ | ✔️ | ❌ |
| fish | ❌ | ⚡ | ⭐⭐⭐⭐⭐ | ❌ | ⭐⭐⭐⭐ |
Vale, ahora entramos ya en “anatomía interna de un shell”. Te lo organizo por bloques para que todo encaje mentalmente.
1. Pipelines: qué son realmente cmd1 | cmd2 | cmd3
Un pipeline no es magia, es solo procesos conectados por pipes del kernel.
1.1. Qué hace el shell al ver A | B | C
Cuando escribes:
bash
A | B | C
El shell hace, conceptualmente:
- Crea dos pipes:
- pipe1: conecta
A→B - pipe2: conecta
B→C
- pipe1: conecta
- forkea un proceso para cada comando:
- hijo1 para
A - hijo2 para
B - hijo3 para
C
- hijo1 para
- En cada hijo:
- Redirige
stdin/stdouta los extremos correctos de los pipes - Cierra los extremos que no usa
- Llama a
execve()con el comando correspondiente
- Redirige
- El shell padre:
- Cierra todos los extremos de los pipes
- Hace
wait()a los hijos (o los registra como jobs)
1.2. A nivel de descriptores de archivo
Un pipe es un par de FDs:
c
int fds[2];
pipe(fds); // fds[0] = lectura, fds[1] = escritura
Para A | B:
- Proceso A:
dup2(fds[1], STDOUT_FILENO);// su stdout va al pipe
- Proceso B:
dup2(fds[0], STDIN_FILENO);// su stdin viene del pipe
Luego cierran los FDs originales y ejecutan execve().
2. File descriptors y redirecciones
2.1. Qué es un file descriptor (FD)
Un file descriptor es simplemente un entero que representa un recurso abierto:
0→ stdin1→ stdout2→ stderr
El kernel mantiene una tabla de FDs por proceso.
2.2. Redirecciones típicas
Ejemplos:
bash
cmd > out.txt # redirige stdout (1) a archivo
cmd 2> err.txt # redirige stderr (2)
cmd > out.txt 2>&1 # stderr → stdout → archivo
cmd < in.txt # stdin desde archivo
Internamente, el shell hace cosas como:
c
int fd = open("out.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
dup2(fd, STDOUT_FILENO);
close(fd);
execve(...);
dup2(oldfd, newfd) hace que newfd apunte al mismo recurso que oldfd.
2.3. Combinando pipes y redirecciones
Ejemplo:
bash
A 2>err.log | B >>out.log
A:stderr(2) →err.logstdout(1) → pipe
B:stdin(0) ← pipestdout(1) →out.logen modo append
3. Mini-shell en C con fork/exec/wait (versión conceptual)
Te hago una versión simplificada, sin pipes ni redirecciones, solo para ver el esqueleto.
3.1. Bucle principal de un shell
Pseudocódigo:
c
while (1) {
mostrar_prompt();
leer_linea(buf);
parsear_linea(buf, argv); // separar en tokens
pid = fork();
if (pid == 0) {
// Hijo
execvp(argv[0], argv);
perror("execvp");
exit(1);
} else {
// Padre
waitpid(pid, &status, 0);
}
}
3.2. Añadiendo redirecciones y pipes
- Antes de
execvp()en el hijo:- Detectas
><2>|en los tokens - Configuras
open(),dup2(),pipe() - Ajustas
argvpara que solo contenga el comando y sus argumentos
- Detectas
- Para pipelines:
- Creas varios hijos
- Conectas sus FDs con
pipe()ydup2() - El padre hace
wait()a todos
La lógica real de Bash/Zsh es mucho más compleja, pero la base es esta.
4. Diferencias profundas entre [[ ]], [ ] y test
Estos tres se usan para condiciones, pero no son equivalentes.
4.1. test y [ ] (POSIX)
test es un comando (builtin o externo):
bash
test "$x" = "hola"
[ ] es simplemente una forma alternativa de escribir test:
bash
[ "$x" = "hola" ]
Detalles:
[es el comando]es solo el último argumento- Es POSIX, existe en sh, bash, zsh, dash…
Problemas típicos:
- Expansiones vacías pueden romper la sintaxis:bash
[ $x = hola ] # si x está vacío → [ = hola ] → error
Por eso siempre se recomienda:
bash
[ "$x" = "hola" ]
4.2. [[ ]] (extensión de Bash/Zsh)
[[ ]] no es un comando, es una construcción del lenguaje (keyword-like).
Ventajas:
- No hace expansión de pathname (globbing)
- Maneja mejor variables vacías
- Permite operadores extra:
[[ $x == patrón ]][[ $x =~ regex ]]
- No requiere comillas en muchos casos:
bash
[[ $x = hola ]]
[[ $x == *.txt ]]
[[ $x =~ ^[0-9]+$ ]]
Esto en [ ] sería peligroso o imposible sin escapes.
4.3. Resumen práctico
- Para scripts POSIX portables: usa
[ ]otest. - Para scripts Bash/Zsh modernos: usa
[[ ]]siempre que puedas.
5. Job control y process groups
Aquí entramos en cómo el shell controla procesos en foreground/background.
5.1. Process groups
Un process group es un conjunto de procesos que el kernel trata como una unidad para señales de terminal.
Ejemplo:
bash
A | B | C
Los tres procesos suelen pertenecer al mismo process group.
¿Por qué?
- Si pulsas
Ctrl+C(SIGINT), la señal se envía al grupo, no solo a uno. - El shell puede parar/reanudar el grupo entero.
5.2. Foreground vs background
Cuando haces:
bash
sleep 100 &
- El shell crea un job en background
- No bloquea el prompt
- El proceso (o grupo) sigue ejecutándose
Cuando haces:
bash
sleep 100
- El job está en foreground
- El shell hace
wait()hasta que termine
5.3. Señales y job control
Señales relevantes:
SIGINT→ Ctrl+CSIGTSTP→ Ctrl+Z (suspender)SIGCONT→ reanudarSIGCHLD→ el hijo ha terminado o cambiado de estado
El shell:
- Recibe
SIGCHLDcuando un hijo termina - Actualiza la tabla de jobs
- Muestra mensajes tipo
[1]+ Done
5.4. Comandos de job control en el shell
jobs→ lista jobsfg %1→ trae job 1 al foregroundbg %1→ reanuda job 1 en backgroundkill %1→ envía señal al job 1
Internamente, el shell usa:
setpgid()/getpgid()para gestionar grupostcsetpgrp()para asignar el terminal al grupo en foreground
6. Cómo encaja todo junto
Cuando ejecutas:
bash
A | B | C >out.txt 2>err.txt &
El shell hace algo así:
- Crea pipes para conectar A→B→C.
- Crea un process group para A, B y C.
- Para cada comando:
fork()- En el hijo:
setpgid()para unirlo al grupodup2()para redirecciones y pipesexecve()del binario
- Marca el job como background (no hace
wait()bloqueante). - Sigue aceptando comandos.
- Cuando los procesos terminan:
- El kernel envía
SIGCHLDal shell - El shell actualiza el estado del job
- El kernel envía