Cuando ejecutas grep para buscar texto en un archivo, estás usando una herramienta que lleva su nombre de una operación interna de un editor de los años 70: g/re/p (“global regular expression print”). No es un nombre caprichoso ni una sigla inventada por un comité de marketing. Es un fósil lingüístico que sobrevivió décadas porque todo el ecosistema que rodea a Linux tiene una raíz común, y entender esa raíz explica muchas decisiones que de otro modo parecen arbitrarias.
Unix nació entre 1969 y 1971 en los laboratorios Bell de AT&T, en Nueva Jersey. Ken Thompson y Dennis Ritchie, junto con otros colegas, estaban construyendo un sistema operativo para uso interno. La restricción era real: hardware caro, memoria escasa, y la necesidad de que el sistema fuera útil de verdad para investigadores que trabajaban con él a diario. De esas restricciones salieron decisiones de diseño que todavía rigen Linux hoy: los archivos son secuencias de bytes sin formato impuesto por el sistema, los programas hacen una sola cosa bien, y la salida de un programa puede alimentar la entrada de otro. Ese último punto —la tubería o pipe— es quizá la idea más influyente que Unix aportó a la informática.
Durante los años 70 y 80, Unix se extendió por universidades y empresas, pero en versiones distintas que empezaban a divergir. Para evitar que el ecosistema se fragmentara sin remedio, en 1988 IEEE publicó POSIX (Portable Operating System Interface), una especificación que define qué comandos debe haber, cómo deben comportarse, cómo funciona el sistema de archivos, qué llamadas al sistema debe ofrecer el kernel. POSIX no es código: es un contrato. Cuando lees que Linux es “compatible con POSIX”, significa que el sistema se comprometió a cumplir ese contrato, lo cual garantiza que un script escrito para un sistema Unix de los 80 tenga muchas probabilidades de ejecutarse sin cambios en Debian hoy.
El problema llegó en 1983. Unix era propietario de AT&T. Las universidades podían estudiarlo, pero no distribuirlo libremente. Richard Stallman, entonces en el MIT, lanzó el proyecto GNU (GNU’s Not Unix) con un objetivo explícito: escribir desde cero un sistema operativo completo y libre —libre como en libertad, no como en gratuito. A lo largo de los 80, GNU produjo herramientas fundamentales: el compilador gcc, el editor emacs, la shell bash, y utilidades esenciales como ls, cp, awk, sed. Para 1991, GNU tenía casi todo un sistema operativo… excepto el kernel, la pieza central que habla directamente con el hardware.
Ese hueco lo llenó Linus Torvalds. En agosto de 1991, un estudiante finlandés de 21 años publicó en un grupo de noticias que estaba escribiendo “un sistema operativo libre, solo un hobby, no va a ser grande ni profesional como GNU”. El kernel Linux apareció con la versión 0.01 ese mismo año. La convergencia fue inmediata: el kernel de Torvalds más las herramientas de Stallman formaron un sistema operativo completo. Por eso el nombre técnicamente correcto es GNU/Linux, aunque en la práctica casi todo el mundo dice solo “Linux”.
Esto importa en el día a día porque explica la filosofía que impregna todo el sistema: los archivos de configuración son texto plano que puedes leer y editar, los programas pequeños se encadenan en lugar de ser monolíticos, y el sistema no intenta protegerte de ti mismo más de lo estrictamente necesario. Cuando algo falla, hay un archivo de log en texto plano que puedes inspeccionar. Esa elección no es accidental: viene directa de los laboratorios Bell hace cincuenta años.
Si alguna vez te preguntas por qué awk se llama así, la respuesta es que son las iniciales de sus creadores: Alfred Aho, Peter Weinberger y Brian Kernighan. Kernighan es también la K de K&R, el libro de C. Estás usando herramientas con nombre de persona porque las escribió gente concreta con un problema concreto que resolver.
# Este comando encadena tres herramientas con décadas de historia
# para contar cuántas veces aparece cada shell en /etc/passwd
# grep filtra solo las líneas que contienen "/bin/" (rutas de shells)
# awk extrae el último campo separado por ":" (la columna del shell)
# sort ordena las líneas para que uniq pueda agrupar duplicados
# uniq -c cuenta cuántas veces aparece cada valor consecutivo
# sort -rn ordena el resultado numéricamente de mayor a menor
grep '/bin/' /etc/passwd \
| awk -F: '{print $NF}' \
| sort \
| uniq -c \
| sort -rn
Fíjate en lo que acaba de pasar: cinco programas independientes, escritos en décadas distintas por personas distintas, encadenados con el operador | (pipe) para resolver un problema concreto. Ninguno de ellos sabe que los otros existen. grep filtra y escribe en su salida estándar; awk lee de su entrada estándar y escribe en la suya; y así sucesivamente hasta que el último resultado llega a tu terminal.
awk -F: '{print $NF}' merece un segundo de atención. -F: le dice a awk que el separador de campos es el carácter dos puntos, que es exactamente el formato de /etc/passwd. $NF es una variable interna de awk que siempre contiene el último campo de la línea actual —NF significa Number of Fields, y $NF es el campo en esa posición. En una línea de /etc/passwd el último campo es el shell asignado al usuario. No necesitas saber cuántos campos hay: $NF lo calcula solo. Eso es diseño Unix: la herramienta te da acceso a la estructura de los datos sin obligarte a contar columnas a mano.
El orden de sort antes de uniq no es opcional: uniq solo colapsa líneas consecutivas idénticas. Si no ordenas primero, dos ocurrencias del mismo shell separadas por otra línea se contarían como entradas distintas. Esta limitación existe porque uniq fue diseñado para procesar streams de datos en una sola pasada, sin almacenar todo en memoria. Hardware de 1970. La restricción original se convirtió en comportamiento estándar, POSIX lo especificó, y cuarenta años después sigues teniendo que recordarlo.
N° 2