Shell 101
Autor
Vanessa Reteguín¿Qué es programación en Shell?
Shell es una interfaz de línea de comando; es decir una forma en la que el usuario puede interactuar con software (aplicaciones específicas) y el sistema operativo por medio de comandos escritos y respuestas dentro de una consola. Es dependiente completamente de inputs desde el teclado y outputs en texto
Poder programar en shell para un programador es como adquirir un nuevo tipo de superpoder ✨ ya que nos permitirá automatizar tareas, manejar procesos, detener ataques (o también atacar, shhh) y más importante: administrar y monitorear efectivamente un sistema.
Así como existen diferentes lenguajes de programación, existen diferentes tipos de Shell; cada uno con comandos propios, herramientas y características. Las más común para Linux es Bash (Bourne Again Shell), para macOS Zsh y para Windows es PowerShell.
¿Cómo saber qué shell tengo en mi equipo?
PowerShell → echo $ShellId
PS C:\Users\Cardui> echo $ShellId
Microsoft.PowerShell
Linux y macOS → echo $SHELL
Arch Linux
[root@alarm /]# echo $SHELL
/bin/bash
macOS
vanessa@MacBook-Air-de-Vanessa Desktop % echo $SHELL
/bin/zsh
En esta ocasión nos enfocaremos en Shell scripting con bash
¿Cómo creo un archivo de Bash?
Un archivo de bash puede iniciar con
#!/path/to/interpreter
Ejemplo: #!/bin/bash
Creemos un archivo de bash:
- Creamos el archivo →
nano test.sh - Dentro del editor nano
#!/bin/bash
echo "Weeenas universo"
echo "The current bash version is: ${BASH_VERSION}"Lo guardamos con ctrl + X
- Nos otorgamos permiso para ejecutar el archivo →
chmod 711 test.sh - Ejecutamos con
./
[root@alarm CarduiDocs]# ./test.sh
Weeenas universo
The current bash version is: 5.1.16(1)-release
Por qué permisos 711?
Los permisos se representan por valores octales que indican los permisos sobre el archivo dependiendo del usuario. Los permisos se asignan numéricamente al sumarlos:
r→ read (leer) → 4w→ write (modificar el archivo) → 2x→ execute (ejecutar) → 1Owner (dueño del archivo) Grupo Otros (fuera del grupo) -rw r– r– 6 4 4 6 = 4 + 2 + 0 4 = 4 + 0 + 0 4 = 4 + 0 + 0 Leer y escribir Sólo leer Sólo leer Por ejemplo, creé el archivo
test.txtcon el editor de texto en consola nano. Por default, este archivo tiene permisos 644. Es decir, sólo su dueño (yo) puedo escribir sobre él, los demás sólo pueden leerlo.vanessa@MacBook-Air-de-Vanessa Desktop % ll total 80840 drwx------@ 9 vanessa staff 288 May 4 08:30 . drwxr-x---+ 46 vanessa staff 1472 May 4 08:23 .. -rw-r--r--@ 1 vanessa staff 8196 May 2 08:23 .DS_Store -rw-r--r-- 1 vanessa staff 0 Jun 20 2025 .localized -rwxr-xr-x@ 1 vanessa staff 4612670 Mar 6 2017 Linux_Server_Security.pdf -rw-r--r--@ 1 vanessa staff 1091318 Apr 30 17:49 Screenshot 2026-04-30 at 17.48.56.png -rwxr-xr-x@ 1 vanessa staff 35660828 Jan 31 2009 linux_server_hacks.pdf drwxr-xr-x 11 vanessa staff 352 May 2 08:23 old -rw-r--r-- 1 vanessa staff 26 May 4 08:30 test.txt vanessa@MacBook-Air-de-Vanessa Desktop % chmod 700 test.txt vanessa@MacBook-Air-de-Vanessa Desktop % ll total 80840 drwx------@ 9 vanessa staff 288 May 4 08:30 . drwxr-x---+ 46 vanessa staff 1472 May 4 08:23 .. -rw-r--r--@ 1 vanessa staff 8196 May 2 08:23 .DS_Store -rw-r--r-- 1 vanessa staff 0 Jun 20 2025 .localized -rwxr-xr-x@ 1 vanessa staff 4612670 Mar 6 2017 Linux_Server_Security.pdf -rw-r--r--@ 1 vanessa staff 1091318 Apr 30 17:49 Screenshot 2026-04-30 at 17.48.56.png -rwxr-xr-x@ 1 vanessa staff 35660828 Jan 31 2009 linux_server_hacks.pdf drwxr-xr-x 11 vanessa staff 352 May 2 08:23 old -rwx------ 1 vanessa staff 26 May 4 08:30 test.txt vanessa@MacBook-Air-de-Vanessa Desktop %
Uso de variables
Variables de ambiente → Almacenar comandos o información que se usa repetidamente en el futuro
Imprimir variables de ambiente → printenv
Ejemplo Linux
[root@alarm CarduiDocs]# printenv
SHELL=/bin/bash
PWD=/CarduiDocs
LOGNAME=alarm
XDG_SESSION_TYPE=tty
SYSTEMD_EXEC_PID=328
MOTD_SHOWN=pam
HOME=/root
LANG=C
INVOCATION_ID=2e68610831a0475e913f5fb06ecef25a
XDG_SESSION_CLASS=user
TERM=vt220
USER=alarm
SHLVL=3
XDG_SESSION_ID=1
XDG_RUNTIME_DIR=/run/user/1000
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
MAIL=/var/spool/mail/alarm
OLDPWD=/
_=/usr/bin/printenv
Ejemplo macOS
vanessa@MacBook-Air-de-Vanessa Desktop % printenv
TERM_PROGRAM=Apple_Terminal
SHELL=/bin/zsh
TERM=xterm-256color
TMPDIR=/var/folders/59/_drbhfms24j_k5_xhs88jhbw0000gn/T/
TERM_PROGRAM_VERSION=470.2
TERM_SESSION_ID=8F63D89F-A1A1-44BA-BEAE-002951646D05
USER=vanessa
SSH_AUTH_SOCK=/var/run/com.apple.launchd.W09Rwm2Gsh/Listeners
PATH=/Library/Frameworks/Python.framework/Versions/3.14/bin:/Library/Frameworks/Python.framework/Versions/3.14/bin:/Library/Frameworks/Python.framework/Versions/3.13/bin:/Library/Frameworks/Python.framework/Versions/3.13/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/pkg/env/global/bin
__CFBundleIdentifier=com.apple.Terminal
PWD=/Users/vanessa/Desktop
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
SHLVL=1
HOME=/Users/vanessa
LOGNAME=vanessa
OSLogRateLimit=64
COLORTERM=truecolor
OLDPWD=/Users/vanessa/Desktop
HOMEBREW_PREFIX=/opt/homebrew
HOMEBREW_CELLAR=/opt/homebrew/Cellar
HOMEBREW_REPOSITORY=/opt/homebrew
FPATH=/opt/homebrew/share/zsh/site-functions:/usr/local/share/zsh/site-functions:/usr/share/zsh/site-functions:/usr/share/zsh/5.9/functions
INFOPATH=/opt/homebrew/share/info:
LANG=C.UTF-8
LC_CTYPE=UTF-8
_=/usr/bin/printenv
Creemos una variable
Comillas simples/dobles (’) (”) → Almacenar una cadena
Backquote (`) → Almacenar el contenido de lo que regrese la ejecución
Variable de ambiente
VAR_NAME=value; export VAR_NAME
vanessa@MacBook-Air-de-Vanessa Desktop % SECRET_IDENTITY='Batman'; export SECRET_IDENTITY
vanessa@MacBook-Air-de-Vanessa Desktop % echo $SECRET_IDENTITY
Batman
Variable de sesión (expira al cerrar)
VAR_NAME=value
vanessa@MacBook-Air-de-Vanessa Desktop % MY_THIS_HOUR=`/bin/date +"%d/%b/%Y:%H"`
vanessa@MacBook-Air-de-Vanessa Desktop % echo $MY_THIS_HOUR
03/Jun/2026:19
Recepción de parámetros
Igual que en una función, hay ocaciones en donde necesitaremos recibir parámetros
Creamos archivo →
nano test.shecho $0 #Nombre del archivo echo "Holi $1" #Primer parámetroNos damos permiso para ejecutar →
chmod 711 test.shEjecutamos con parámetro →
./test.sh 'Gru'vanessa@MacBook-Air-de-Vanessa Desktop % ./test.sh 'Gru' ./test.sh Holi Gru
Condicionales
Sintaxis general
if [ condition ]
then
statement
else
do this by default
fiEjemplo:
MY_FILE=test.sh
if [ -f "$MY_FILE" ]; then
echo 'YES!'
else
echo 'Nein, 404 ):'
fivanessa@MacBook-Air-de-Vanessa Desktop % MY_FILE=test.sh
if [ -f "$MY_FILE" ]; then
echo 'YES!'
else
echo 'Nein, 404 ):'
fi
YES!
Ciclos y Órdenes de evaluación de expresiones
Los ciclos for y while nos serán muy útiles para leer logs y poder detectar patrones. A continuación un ejemplo de cómo podemos extraer información de un archivo:
- Creemos un archivo de prueba →
nano heroes.txt
heroes.txt
1. Spider Man - Peter Parker
2. Iron Man - Tony Stark
3. Captain America - Steve Rogers
4. Thor - Thor Odinson
5. Hulk - Bruce Banner
6. Black Widow - Natasha Romanoff
7. Wolverine - Logan
8. Doctor Strange - Stephen Strange
9. Black Panther - T'Challa
10. Captain Marvel - Carol Danvers
11. Deadpool - Wade Wilson
12. Daredevil - Matt Murdock
13. Ant Man - Scott Lang
14. Hawkeye - Clint Barton
15. Scarlet Witch - Wanda Maximoff
16. Vision - Victor Shade
17. Luke Cage - Carl Lucas
18. Mister Fantastic - Reed Richards
19. Invisible Woman - Sue Storm
20. Loki - Loki Laufeyson
- Leemos cada línea del archivo
awk → Utilidad de procesamiento de texto de bash
| → ‘Pipe’ (entubar) → Redirigir el contenido o output
de un comando hacia otro
'{print $2}' → Imprimir sólo el segundo conjunto de
elementos de la línea (campos)
while read p; do
echo $p | awk {'print $2'}
done < heroes.txtSpider
Iron
Captain
Thor
Hulk
Black
Wolverine
Doctor
Black
Captain
Deadpool
Daredevil
Ant
Hawkeye
Scarlet
Vision
Luke
Mister
Invisible
LokiSupongamos que queremos encontrar sólo los registros con un cierto nombre o que contengan una cierta cadena. Empleamos la utilidad de grep para buscar patrones y devolver las coincidencias:
while read p; do
echo $p | grep 'Man'
done < heroes.txt1. Spider Man - Peter Parker
2. Iron Man - Tony Stark
13. Ant Man - Scott Lang
Ahora pensemos en tomar información dentro de un delimitador específico (obtener el nombre completo de nuestro super héore)
awk → Utilidad de procesamiento de texto de bash
-F'[.-]' → Tomar como separador ‘.’ y ‘-’ en lugar de
espacios (delimitador)
'{print $2}' → Imprimir sólo el segundo conjunto de
elementos de la línea (campos)
while read p; do
echo $p | awk -F'[.-]' '{print $2}'
done < heroes.txt Spider
Iron Man
Captain America
Thor
Hulk
Black Widow
Wolverine
Doctor Strange
Black Panther
Captain Marvel
Deadpool
Daredevil
Ant
Hawkeye
Scarlet Witch
Vision
Luke Cage
Mister Fantastic
Invisible Woman
Loki
Un ciclo for estándar
for i in {1..5}
do
echo $i
done1
2
3
4
5
También se pueden hacer ciclos anidados con condiciones
for i in {1..5}
do
echo ""
for j in {1..5}
do
if (( j % 2 == 0 )); then
echo -n '■'
else
echo -n '□'
fi
done
done□■□■□
□■□■□
□■□■□
□■□■□
□■□■□