Terminal, shell, zsh y PowerShell: qué es cada cosa
Todos los días le das órdenes a tu computadora. Lo que pasa es que no lo vives así: tú abres una carpeta, arrastras un archivo, haces clic derecho y eliges una opción. Se siente como usar la computadora, no como darle instrucciones. Pero cada clic es exactamente eso —una orden.
Este post es sobre la otra forma de dar esas mismas órdenes: escribiéndolas. Y sobre las tres palabras que se cruzan en el camino y que casi nadie te explica en orden: terminal, shell y script.
1. Señalar o dictar
Hay dos formas de darle órdenes a una computadora: señalar o dictar.
1) Cuando usas el mouse, señalas. Es cómodo y no tienes que aprender nada —pero solo puedes hacer lo que alguien ya dibujó en la pantalla, y tienes que hacerlo una vez por cada elemento.
2) Cuando usas la terminal, dictas. Escribes la orden en palabras. Es más incómodo al principio, y aquí viene lo importante: la ventaja real no es que la computadora se vuelva más potente. Copiar 100 archivos cuesta lo mismo por dentro, lo hagas como lo hagas.
Lo que cambia es quién hace el trabajo repetitivo:
- Con el mouse, tú ejecutas la acción 100 veces.
- Con la terminal, tú describes la acción una vez y la máquina la ejecuta 100 veces.
Ese es el salto completo: pasas de ejecutar a describir. Y describir no se cansa, no se distrae, y no se equivoca en el archivo número 73.
Piensa en una tarea real: buscar dentro de veinte carpetas todos los archivos cuyo nombre empiece con "a", y copiarlos a otra carpeta ordenados. Con el mouse es una tarde entera entrando y saliendo de carpetas. Dictada, es una línea. La tarea no cambió de dificultad —cambió quién la repite.
2. La terminal: la mínima interfaz gráfica posible
Aquí hay una paradoja que me gusta mucho.
La terminal es una aplicación gráfica: tiene ventana, pestañas, tipografía, colores. Lo que la hace distinta es que renunció a casi toda su parte gráfica. No te ofrece nada que señalar —solo un lugar donde escribir.
La terminal es la mínima cantidad de interfaz gráfica necesaria para dejar de usar interfaz gráfica.
Su nombre completo es emulador de terminal, y viene de algo literal: antes existían terminales físicas, una pantalla con teclado y sin computadora propia, conectada por cable a una máquina central. Las aplicaciones de hoy emulan aquel aparato.
En el día a día basta con decirle terminal. Es el término genérico correcto y se entiende en cualquier sistema. También verás la palabra consola, que se usa como sinónimo.
Y ahora el punto que ordena todo lo demás: la terminal no entiende ni un solo comando. Es una ventana. Dibuja lo que escribes y muestra lo que le devuelven. Nada más.
Entonces, ¿quién te entiende?
3. El shell: quien te escucha
Dentro de esa ventana corre un programa cuyo trabajo es escucharte. Se llama shell.
Es la palabra que más confusión genera, así que vale la pena decir qué no es: el shell no es la ventana, y tampoco es el idioma. El shell es un programa, y hace tres cosas:
- Define la gramática — las reglas con las que le hablas.
- Entiende lo que escribiste — expande comodines, resuelve variables, separa el comando de sus argumentos.
- Manda a ejecutar — localiza los programas necesarios, los lanza, los conecta entre sí y espera resultados.
La imagen que mejor le queda es la de un capataz de obra: le hablas en su idioma, te entiende, y moviliza a los obreros —que son los programas ya instalados— para que hagan el trabajo. No te da clases: obedece y organiza.
Cada sistema trae el suyo
Tu computadora ya tiene un shell instalado, vengas de donde vengas:
| Sistema | Shell por defecto |
|---|---|
| Mac | zsh (Z Shell) |
| Windows | PowerShell |
| Linux | bash en la mayoría de distribuciones |
Dos aclaraciones que evitan malentendidos:
- Un sistema no habla un solo idioma. Tu Mac trae zsh por defecto, pero también tiene bash instalado. Windows trae PowerShell y además CMD, y puede correr bash de Linux por dentro. Cada sistema tiene una lengua materna, pero puede aprender otras.
- El lenguaje se llama igual que el programa, y de ahí viene medio enredo. Es como si a la persona que te atiende la llamaran "Español" y al idioma que habla también "Español". Preguntas ¿quién me atiende? → zsh. ¿En qué idioma le hablo? → zsh. Mismo nombre, dos cosas distintas.
Y sí, ese lenguaje es un lenguaje de programación, aunque no lo parezca. Tiene variables, condicionales, bucles y funciones. Lo que lo hace sentir distinto es que puedes usarlo de a una línea a la vez: escribes una instrucción, pulsas Enter, ves el resultado. En la mayoría de lenguajes primero escribes el archivo completo y después lo ejecutas.
Esa particularidad es la que hace posible lo que viene ahora.
4. El script: órdenes guardadas
Un script es un archivo de texto con una lista de instrucciones que la computadora ejecuta una por una, en orden.
Y aquí está el mejor regalo de todo esto:
Lo que escribes en un script es literalmente lo mismo que escribirías a mano en la terminal.
No hay un segundo lenguaje. No hay un "modo script". Es la misma conversación, guardada en un archivo para no tener que repetirla. Si ya sabes escribir tres comandos en la terminal, ya sabes escribir un script de tres líneas: son esos mismos comandos, uno debajo del otro.
Por eso la definición corta que uso es esta:
Scripting es escribir en un archivo las mismas órdenes que escribirías a mano en la terminal, para no tener que volver a escribirlas.
5. Lo mínimo para empezar, en los dos idiomas
Hasta aquí todo fue mapa. Bajemos a la tierra con lo mínimo indispensable —lo justo para que puedas abrir la terminal hoy y no quedarte mirando el cursor.
5.1 La forma de una orden
Antes de cualquier lista, la gramática, porque es siempre la misma en los dos sistemas:
comando -opciones argumentos
- Comando — qué quieres hacer
- Opciones — cómo lo quieres (empiezan con guion)
- Argumentos — sobre qué lo quieres
Y un detalle que evita el primer tropiezo de todo el mundo: el espacio separa las piezas. Por eso un nombre con espacios necesita comillas —cd "Mi unidad"—, porque sin ellas el shell cree que le pasaste dos argumentos distintos.
5.2 Las órdenes básicas
Las mismas acciones, dichas en cada idioma:
| Qué quieres hacer | Mac (zsh) | Windows (PowerShell) |
|---|---|---|
| Saber en qué carpeta estás | pwd |
Get-Location |
| Listar lo que hay aquí | ls |
Get-ChildItem |
| Entrar a una carpeta | cd informes |
Set-Location informes |
| Subir un nivel | cd .. |
Set-Location .. |
| Crear una carpeta | mkdir informes |
New-Item -ItemType Directory informes |
| Copiar un archivo | cp a.txt b.txt |
Copy-Item a.txt b.txt |
| Mover o renombrar | mv viejo.txt nuevo.txt |
Move-Item viejo.txt nuevo.txt |
| Borrar un archivo | rm notas.txt |
Remove-Item notas.txt |
| Ver el contenido de un archivo | cat notas.txt |
Get-Content notas.txt |
Compara las dos columnas y verás el carácter de cada idioma:
- zsh es corto. Nombres de dos o tres letras, heredados de una época en que escribir costaba caro. Rápido de teclear, imposible de adivinar.
- PowerShell es explícito. Todo sigue el patrón Verbo-Sustantivo:
Get-,Set-,New-,Copy-,Move-,Remove-. Cansa más al escribir, pero si sabes el verbo y el sustantivo, adivinas el comando sin buscarlo.
En Windows, además,
ls,cd,cp,mv,rmycattambién funcionan: PowerShell los trae como alias de sus cmdlets. Es un gesto amable para quien viene de Unix —pero cuidado, son solo apodos. Por dentro se ejecutaGet-ChildItem, y las opciones no son las mismas que en Mac.
Una advertencia que vale para los dos sistemas: borrar desde la terminal no manda nada a la papelera. No hay confirmación ni deshacer. Con rm y con Remove-Item, lee dos veces antes de pulsar Enter.
5.3 Cuando no sepas qué hace algo
No hay que memorizar nada; hay que saber preguntar:
| Mac (zsh) | Windows (PowerShell) | |
|---|---|---|
| Ver el manual de un comando | man ls |
Get-Help Get-ChildItem |
| Saber qué es un comando | type ls |
Get-Command ls |
Y tres teclas que valen más que media lista de comandos, iguales en ambos:
- Tab — autocompleta nombres. Úsala siempre: además de ahorrar tiempo, evita errores de tipeo.
- Flecha arriba — recupera los comandos anteriores.
- Ctrl + C — cancela lo que esté corriendo.
Con esto ya te mueves en cualquiera de los dos. Y viendo lo distintos que se ven, la pregunta cae sola: ¿por qué dos programas que hacen lo mismo terminaron hablando tan diferente?
6. Las cuatro shells que te vas a cruzar
Ya viste zsh y PowerShell lado a lado. Hay dos más rondando por ahí, y conviene saber de dónde viene cada una —porque no son cuatro versiones de la misma idea:
| Shell | Familia | Origen |
|---|---|---|
bash |
Unix | Descendiente del Bourne Shell de los años 70 |
zsh |
Unix | Misma familia que bash, versión más moderna |
| CMD | DOS | Heredero de MS-DOS, años 80 |
| PowerShell | .NET | Diseñado desde cero en 2006, sin herencia |
Esa tabla reordena el mapa entero:
- bash y zsh son casi el mismo idioma. Dialectos. Prácticamente todo lo que escribes en uno funciona igual en el otro. Pasar de bash a zsh es como pasar del español de España al de México: acento y modismos distintos, entendimiento total.
- CMD y PowerShell no son parientes. PowerShell no es "el CMD moderno" —es un diseño hecho desde cero porque CMD ya no daba más.
- PowerShell tampoco es pariente de bash. Es una tercera cosa, sin relación con ninguna de las otras dos.
Así que la simetría es falsa: en Mac tienes dos dialectos de la misma lengua; en Windows, dos lenguas sin parentesco.
No todas alcanzan lo mismo
Aquí hay una jerarquía real y prefiero decirla sin diplomacia: CMD es una pieza de museo que aún respira. Lenguaje pobre, sin funciones de verdad, manejo de errores casi inexistente y una sintaxis heredada de los años 80. Sigue ahí por compatibilidad con archivos .bat antiguos, no porque sea una buena opción. Si abres una terminal en Windows hoy, no es en CMD donde quieres escribir.
Las otras tres —bash, zsh y PowerShell— son lenguajes completos, con variables, condicionales, bucles y funciones. Con cualquiera de las tres puedes escribir cosas serias.
Texto contra objetos
Entre las tres opciones serias hay una división de fondo que vale la pena conocer desde el principio:
- bash y zsh mueven texto. Todo lo que sale de un comando es una cadena de caracteres. Si quieres el tamaño de un archivo, recortas la columna correcta de ese texto.
- PowerShell mueve objetos. Lo que sale de un comando conserva su estructura, con propiedades que tienen nombre. No recortas nada: pides la propiedad.
Ninguno es mejor. Son dos apuestas distintas: el mundo Unix cree que el texto es el formato universal que todos entienden; PowerShell cree que perder la estructura para luego reconstruirla a mano es un desperdicio.
7. Ejemplo práctico: ordenar los Excel de Downloads
Un último dato antes del ejemplo, y es el que lo vuelve legible: la mayoría de los comandos que usas no pertenecen al shell. ls, git o python son programas independientes instalados en tu sistema; el shell solo los localiza, los ejecuta y los conecta entre sí. Los programas son los electrodomésticos —el shell es la instalación eléctrica.
Con eso en mente, vamos a un caso real y bastante universal: tu carpeta de descargas es un basurero, y ahí dentro viven mezclados PDFs, imágenes, instaladores y un montón de archivos de Excel. Queremos que todos los Excel se vayan a una carpeta mis-excels, dentro de la misma carpeta de descargas.
7.1 En Mac, con zsh
Son dos líneas:
mkdir -p ~/Downloads/mis-excels
mv ~/Downloads/*.xls* ~/Downloads/mis-excels/
Qué hace cada pieza:
mkdir -pcrea la carpeta. La opción-psignifica "no te quejes si ya existe" —así el comando sirve tanto la primera vez como todas las siguientes.*.xls*es el comodín, y está construido con intención. El*de la izquierda acepta cualquier nombre de archivo; el.xlsfija la parte que nos importa; el*de la derecha acepta cualquier cosa que venga después. Con eso caen de una sola vez los.xls, los.xlsxy los.xlsm.mvmueve.
Y aquí está lo interesante, que conecta con todo lo anterior: mv nunca ve un asterisco. El shell expande el comodín antes de llamarlo, y le entrega la lista real de archivos ya resuelta. mv es un programa tonto que recibe nombres concretos; la inteligencia de "busca todo lo que se parezca a esto" la puso el shell.
Si en tu carpeta no hay ningún Excel, zsh responde
no matches foundy no hace nada. No es un error grave —es zsh avisándote de que no encontró a qué aplicar la orden.
7.2 En Windows, con PowerShell
Lo mismo, en el otro idioma:
New-Item -ItemType Directory -Force "$HOME\Downloads\mis-excels"
Get-ChildItem "$HOME\Downloads" -Filter *.xls* | Move-Item -Destination "$HOME\Downloads\mis-excels"
Las equivalencias se leen solas: New-Item -ItemType Directory es el mkdir, y -Force cumple el papel del -p (no protestar si la carpeta ya está). Get-ChildItem es el ls y Move-Item es el mv.
Pero fíjate en la diferencia de fondo, que no es cosmética: en zsh el shell expandió el comodín a texto y se lo pasó a mv. En PowerShell, Get-ChildItem entrega objetos —archivos con sus propiedades intactas— y la tubería se los pasa a Move-Item, que sabe qué hacer con ellos. Es exactamente la diferencia entre texto y objetos que veíamos antes, ocurriendo en una línea que resuelve el mismo problema.
7.3 De la terminal al archivo: esto ya es un script
Aquí viene la parte que hace que todo valga la pena. Lo que acabas de escribir a mano se guarda tal cual en un archivo y se convierte en un script. No hay que traducir nada, no hay que adaptar nada: son las mismas líneas.
En Mac, creas un archivo llamado organizar-excels.sh con esto dentro:
#!/bin/zsh
mkdir -p ~/Downloads/mis-excels
mv ~/Downloads/*.xls* ~/Downloads/mis-excels/
echo "Listo: Excels ordenados."
Solo se agregó una línea nueva, la primera. Se llama shebang (#!) y le dice al sistema con qué shell ejecutar el archivo. Todo lo demás es idéntico a lo que escribiste en la terminal.
Falta un paso que confunde a todo el mundo la primera vez: un archivo de texto no se puede ejecutar hasta que le des permiso. Si lo intentas antes, el sistema responde permission denied. El permiso se da una sola vez:
chmod +x organizar-excels.sh
./organizar-excels.sh
El ./ del final no es decorativo: significa "el archivo que está en esta carpeta". Sin él, el shell buscaría un programa llamado organizar-excels.sh entre los instalados del sistema, y no lo encontraría.
En Windows el archivo se llama organizar-excels.ps1 y se ejecuta así:
.\organizar-excels.ps1
No hace falta dar permisos como en Mac, pero hay otra barrera: por seguridad, Windows viene configurado para no ejecutar scripts de PowerShell. La primera vez tendrás que autorizarlo para tu usuario:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
Dos apuntes sobre los nombres: en Mac la extensión habitual es .sh (también verás .zsh), y en Windows es .ps1. Y en ninguno de los dos casos la extensión es lo que hace funcionar al archivo —en Mac manda el shebang, y en Windows manda con qué programa lo ejecutas. La extensión es para los humanos.
Ese es todo el misterio del scripting: el archivo no contiene nada que no hubieras escrito a mano.
8. Cuándo esto se vuelve programación
Nuestro script tiene un defecto que aparece al segundo mes de usarlo: si vuelves a descargar un archivo que se llama igual que uno ya archivado, lo pisa. Digamos que quieres que cada archivo llegue con la fecha delante.
Eso ya no se resuelve con una lista fija de órdenes:
for archivo in ~/Downloads/*.xls*(N); do
mv "$archivo" ~/Downloads/mis-excels/$(date +%F)-$(basename "$archivo")
done
Quién es quién en esas tres líneas:
| Pieza | De quién es |
|---|---|
for ... in ... do ... done |
Shell — la estructura de bucle |
~/Downloads/*.xls* |
Shell — expande el comodín a la lista real |
(N) |
Shell — extra de zsh: si no hay coincidencias, la lista queda vacía y el bucle simplemente no corre (en vez del no matches found) |
archivo y "$archivo" |
Shell — declarar la variable y leerla |
$( ... ) |
Shell — ejecuta algo y pone su resultado ahí mismo |
date |
Programa externo — dice la fecha |
basename |
Programa externo — se queda solo con el nombre del archivo, sin la ruta |
De siete piezas, cinco son del shell. Los dos programas externos son los más tontos de la línea: uno dice la fecha y el otro recorta una ruta. Toda la inteligencia —recorrer, componer el nombre nuevo, saltarse el caso vacío— la pone el shell.
Y aquí está la frontera que da nombre a esta sección:
- Automatizar es guardar una lista fija de órdenes. El script hace siempre exactamente lo mismo. Es una grabación.
- Programar empieza cuando esa lista deja de ser fija: cuando aparecen variables (guardar un valor para reusarlo), bucles (repetir para cada elemento) y condicionales (hacer algo solo si se cumple algo).
Fíjate en cómo llegamos: no te sentaste a programar. Querías que los archivos no se pisaran, y para eso hacía falta tratar a cada archivo por separado. Salieron el bucle y la variable solos, empujados por el problema.
Así es como se cruza esa frontera en la vida real —por pereza y por necesidad, no por ambición.
9. ¿Y Python dónde entra?
Si con el shell ya puedo automatizar, ¿para qué querría Python? Es la pregunta correcta, y conviene empezar por deshacer un malentendido: no compiten.
9.1 Python es un programa más
Preguntémosle al sistema qué es cada cosa:
ls is /bin/ls
python3 is /opt/homebrew/bin/python3
Ahí está la respuesta: para el shell, python3 y ls son exactamente la misma clase de cosa. Un archivo instalado en una carpeta del sistema, que el shell localiza y ejecuta cuando escribes su nombre. Python no es una tecnología de otro rango —es un programa, como todos los demás.
Y cuando lo lanzas, pasa lo de siempre: el shell lo arranca como un proceso aparte y se hace a un lado a esperar. Mientras Python trabaja, el shell no está interpretando nada. Cuando Python termina, el shell recupera el control y te devuelve el prompt.
O sea que Python no vive dentro del shell. El shell es quien lo lanza.
9.2 Dos formas de construir lo mismo
Aclarado eso, la diferencia real entre uno y otro no es de potencia, es de cómo arman las piezas:
| Shell | Python | |
|---|---|---|
| Qué combina | Programas | Librerías |
| Cómo se conectan | Tuberías entre programas | import dentro del mismo programa |
| Qué viaja entre las piezas | Texto | Datos con su estructura intacta |
El mundo del shell dice: muchos programas pequeños, cada uno hace una cosa bien, y yo los conecto con texto. Python dice: un solo programa, con librerías para todo, y los datos nunca se aplanan.
De ahí sale la razón de fondo por la que Python gana cuando la cosa se complica. En una tubería del shell, cada paso convierte los datos a texto y el siguiente tiene que volver a interpretarlos. Con dos pasos es elegante. Con ocho pasos y datos que tienen estructura, acabas dedicando más tiempo a recortar texto que a resolver el problema.
9.3 Cuál elegir
El criterio es más simple de lo que parece: ¿necesitas una librería?
Mientras trabajes con los archivos por fuera —moverlos, renombrarlos, copiarlos, buscarlos por nombre, comprimirlos— el shell te sobra. Nada de eso necesita librerías, y hacerlo en Python sería dar un rodeo para llegar al mismo sitio.
En cambio, en el momento en que necesitas entrar al contenido, aparece la librería, y con ella Python:
| Lo que quieres hacer | La librería que lo resuelve |
|---|---|
| Leer un Excel y sumar una columna | openpyxl o pandas |
| Cruzar dos CSV grandes por una columna en común | pandas |
| Pedir datos a una API y quedarte con dos campos del resultado | requests |
| Sacar las tablas de un PDF y volcarlas a un Excel | pdfplumber |
Ninguna de esas cuatro cosas se hace cómodamente en zsh, y las cuatro son media docena de líneas en Python.
En una frase: mover archivos es shell; abrir archivos es Python.
9.4 Lo que cuesta cada uno
Antes de concluir "entonces siempre Python", hay una contrapartida que decide más casos de los que parece:
- Las piezas del shell ya están instaladas.
grep,sort,mvofindestán en cualquier Mac y en cualquier Linux del mundo. Cero instalación, cero configuración, funcionan hoy. - Las librerías de Python hay que instalarlas y mantenerlas: entornos virtuales, versiones que chocan, una lista de dependencias que acompaña al script a todos lados.
Por eso el shell gana en lo pequeño. No porque sea más capaz, sino porque empezar no cuesta nada. Para mover unos archivos, montar un entorno de Python es traer una grúa para levantar una silla.
Y no es una elección excluyente. Lo más común en la práctica es el shell llamando a Python: el shell decide qué archivos hay que procesar y se los pasa a un script que hace el trabajo fino. Cada uno en lo suyo.
9.5 Una aclaración de alcance
Todo lo anterior compara shell y Python para una cosa concreta: automatizar tareas. Y ahí la frontera es la que vimos. Pero sería injusto dejar al shell como "eso que mueve archivos", porque su verdadero terreno es otro: operar la máquina.
Ver qué procesos están corriendo y matar el que se colgó. Revisar cuánto disco queda. Leer los logs de un servicio en vivo mientras falla. Gestionar permisos, instalar software, programar tareas que corran solas de madrugada. Nada de eso es automatizar —es administrar el sistema, y se hace desde el shell.
Y hay un lugar donde deja de ser una opción: cuando te conectas a un servidor Linux no hay escritorio. No hay ventanas que señalar ni menús donde buscar. Aterrizas en un shell y eso es todo lo que hay. Por eso quien administra servidores vive en la terminal —no por gusto, sino porque es la única puerta de entrada.
La buena noticia para quien empieza en un Mac: lo que aprendes de zsh se transfiere casi entero a esos servidores, porque zsh y bash son de la misma familia. No estás aprendiendo algo que solo sirva en tu computadora.
10. Mi conclusión
Si tuviera que resumir el mapa en cinco frases:
- La terminal es la ventana donde escribes. No entiende nada; solo transporta.
- El shell es el programa que te escucha dentro de esa ventana, entiende tu orden y la manda a ejecutar. Define la gramática y coordina a los demás programas.
- Los comandos que usas casi siempre son programas independientes. El shell no los provee: los conecta.
- Un script es esa misma conversación guardada en un archivo, para no repetirla.
- Python empieza donde el shell se queda corto: el shell mueve las cajas, Python las abre.
Lo que cambia entre Mac y Windows es el idioma —zsh en un lado, PowerShell en el otro— pero el concepto es idéntico en los dos. Aprenderlo una vez sirve para ambos; después solo cambias de vocabulario.
Mi recomendación para empezar hoy: no busques una lista de comandos para memorizar. Busca algo que hagas repetido y pregúntate cómo lo dictarías. Ese es el único punto de partida que no se olvida a los dos días.
11. Recursos
12. Pendientes
- [ ] Post aparte sobre por qué la terminal de Mac se siente más fácil que la de Windows: Unix nació para la terminal y Windows para el mouse, "todo es un archivo", y el hecho de que casi toda la documentación de internet asume Unix. Con la parte incómoda incluida: nada de eso significa que PowerShell sea peor lenguaje —de hecho está mejor diseñado que bash en varios frentes.
- [ ] Verificar en Windows los comandos de PowerShell del post antes de publicarlo. Los de zsh están probados; los de PowerShell están escritos según la documentación oficial pero no ejecutados.
- [ ] Continuación del script de los Excel: hacer que se ejecute solo cada día, sin lanzarlo a mano (
launchden Mac, Programador de tareas en Windows).