25 puntos por GN⁺ 2026-02-28 | 1 comentarios | Compartir por WhatsApp
  • Es una sintaxis de redirección que se usa para combinar el error estándar (stderr) y la salida estándar (stdout) en un solo flujo
  • Los números 1 y 2 significan stdout y stderr, respectivamente, y & se usa para indicar que se está haciendo referencia a un descriptor de archivo
  • 2>&1 significa “enviar stderr al lugar al que stdout está apuntando actualmente”, y el resultado cambia según el orden de la salida
  • Por ejemplo, command >file 2>&1 envía ambos flujos al archivo, pero command 2>&1 >file deja solo stderr en la consola
  • Es una sintaxis de redirección clave que se usa con frecuencia en Bash y shells POSIX para combinar salidas, guardar logs y trabajar con pipes

Descriptores de archivo y conceptos básicos

  • 0, 1, 2 significan stdin, stdout, stderr, respectivamente
    • Están definidos en /usr/include/unistd.h
    • #define STDIN_FILENO 0, #define STDOUT_FILENO 1, #define STDERR_FILENO 2
  • > es redirección de salida, `` es escribir el archivo desde cero, >> es agregar al archivo
  • El símbolo & indica que se está haciendo referencia a un descriptor y no a un nombre de archivo
    • Por eso, 2>1 redirige a un archivo llamado 1, mientras que 2>&1 duplica stderr hacia stdout

Cómo funciona 2>&1

  • 2> significa redirigir stderr, y &1 hace referencia al descriptor de archivo de stdout
  • Como resultado, stderr pasa a apuntar al mismo destino que stdout
  • Ejemplos:
    • ls -ld /tmp /tnt >/dev/null 2>&1 → ambas salidas se descartan en /dev/null
    • ls -ld /tmp /tnt 2>&1 >/dev/null → solo stderr permanece en la consola
  • Las redirecciones se procesan de izquierda a derecha, así que si cambia el orden, también cambia el resultado

La importancia del orden en la redirección

  • command >file 2>&1
    • Primero envía stdout al archivo y luego duplica stderr hacia stdout → ambos flujos van al archivo
  • command 2>&1 >file
    • Primero duplica stderr hacia el stdout actual (la consola) y luego envía solo stdout al archivo → stderr sigue saliendo en la consola
  • Bash procesa las redirecciones en orden, así que al escribir comandos hay que tener cuidado con la secuencia

Varios ejemplos de redirección

  • echo test >file.txt → stdout al archivo
  • echo test 2>file.txt → stderr al archivo
  • echo test 1>&2 → stdout hacia stderr
  • command &>file o command >&file → stdout y stderr al archivo (forma abreviada de Bash)
  • command 2>&1 | tee -a file.txt → muestra ambos flujos al mismo tiempo en el archivo y en la terminal

Uso avanzado y funciones desde Bash 4.0

  • Desde Bash 4.0, se puede separar la salida usando sustitución de procesos
    • ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
    • Envía stdout y stderr a filtros distintos
  • |& es la forma abreviada de 2>&1 |, y sirve para pasar ambos flujos combinados por un pipe
  • La opción set -o noclobber evita sobrescribir archivos existentes, y se puede hacer una excepción con >|

Ejemplos de uso práctico

  • g++ main.cpp 2>&1 | head → ver solo la salida inicial, incluidos los errores de compilación
  • perl test.pl > debug.log 2>&1 → guardar toda la salida y los errores en un archivo de log
  • foo 2>&1 | grep ERROR → buscar la cadena ERROR tanto en stdout como en stderr
  • docker logs container 2>&1 | grep "some log" → pasar todo el log por un pipe

Resumen clave

  • 2>&1 es una sintaxis estándar de POSIX para duplicar stderr hacia stdout
  • El orden de la redirección determina el resultado, así que hay que prestar atención al escribir comandos
  • En Bash, &> permite manejar ambos flujos a la vez, y
    se usa de forma esencial en muchos scripts de automatización para gestionar logs, pipes y combinación de errores

1 comentarios

 
GN⁺ 2026-02-28
Comentarios en Hacker News
  • Desde la perspectiva de la API de syscalls de Unix, 2>&1 significa lo mismo que dup2(1, 2)
    En los shells clásicos de Unix, eso es todo, pero en los shells modernos se agrega bookkeeping interno para rastrear el estado
    la redirección se ejecuta secuencialmente de izquierda a derecha, y el operador pipe funciona como una combinación de fork y dup
    Eso sí, aunque entender dup2(2, 1) como 2<1 parezca intuitivo, en términos de I/O es una interpretación incorrecta

    • Busqué “dup2(2, 1)” en Safari de iPhone y este hilo salió en segundo lugar
      Estaba entre la documentación de man7 para dup2 y la documentación de Arch Linux para dup2
      Sorprende que los bots estén leyendo esto
    • Creo que por eso mucha gente siente incomodidad con el lenguaje de shell POSIX
      Hay demasiada azúcar sintáctica y termina ocultando los mecanismos internos
      A diferencia de lenguajes como Lisp, que expanden estructuras simples con macros, el shell tiene reglas sintácticas complejas y poco intuitivas
      Al final, parece que este tipo de quejas nace del choque de egos entre programadores y administradores de sistemas
    • Una aplicación interesante de esta técnica es configurar file descriptors no inicializados
      >&1 echo "stdout"
      >&2 echo "stderr"
      >&3 echo "fd 3"
      ./foo.sh 3>&1 1>/dev/null 2>/dev/null
      
      Así puedes dejar solo una salida específica y silenciar todo lo demás
      Eso sí, si no lo abres antes, aparece el error “Bad file descriptor”
    • Cuando el shell ejecuta un programa, siempre hace fork
      La redirección usa dup antes de exec, y el pipe usa dos forks y la syscall pipe
      El manual de BASH está muy bien hecho, así que conviene consultar la documentación oficial
    • Hay una fuerte consistencia entre la API de Unix, C, el shell y Perl
      Pero en lenguajes modernos o fuera del ecosistema Unix, esa intuición se pierde
  • Al final, lo más seguro es leer directamente la documentación oficial (RTFM)
    Manual de Bash Redirections

    • Claro, pocas personas saben dónde buscar
      La mayoría encuentra respuestas googleando, y esos resultados solo existen porque antes se acumularon esas preguntas
      Las distintas perspectivas de Stack Overflow ayudan más a quienes están empezando
    • Pero hoy en día la búsqueda de Google ya no sirve
      Para los usuarios comunes es difícil encontrar la información que quieren
  • Una respuesta de Stack Overflow expresa exactamente lo que pienso, así que la cito tal cual
    La razón por la que es 2>&1 y no &2>&1 es que & solo significa file descriptor en el contexto de redirección
    Es interesante que PowerShell haya mantenido la misma sintaxis

    • PowerShell tiene 7 streams: Success, Error, Warning, Verbose, Debug, Information, Progress
      Enlace a la documentación oficial
    • Pero PowerShell tomó prestada la sintaxis y arruinó la semántica
      El orden de 2>&1 > file es el inverso de Unix, así que no produce el resultado esperado
      Antes de la versión 7.4 también existía un problema de corrupción de byte streams
      Documento relacionado
    • El número antes de > especifica qué file descriptor se va a redirigir
      >foo es lo mismo que 1>foo
      Si escribes 2>>&1, terminas creando un archivo llamado 1, así que no tiene sentido
    • En realidad no hay motivo para confundirse
      > significa stdout, 2> significa stderr, y &1 significa stdout
    • file1>file2 tampoco es simétrico
      /dev/stderr>/dev/stdout sería una correspondencia más directa
  • La explicación de Claude fue la más fácil de entender
    2>&1 significa “envía la salida de error al mismo lugar que la salida estándar”

    • 2 es la salida de error, > significa “enviar”, y &1 significa “a donde apunta stdout actualmente”
    • Si se quiere ser más preciso, 2 significa file descriptor 2, > significa asignación, y &1 significa file descriptor 1
    • Pero esta explicación es casi igual a la segunda respuesta de Stack Overflow (la respuesta de dbr)
      Es más eficiente hacer clic directamente en el enlace que obtenerlo a través de un LLM
  • Me hace extrañar la época de Stack Overflow en la que uno le preguntaba a personas
    Pero ahora ya es difícil volver a esos tiempos

    • Desde 2025, la nostalgia por “los buenos viejos tiempos” creció de repente
      Pero incluso entonces había mucho gatekeeping y un ambiente cínico
      La colaboración centrada en humanos no siempre era romántica
    • Antes me gustaban las respuestas de IA sin relleno
      Iban directo al punto sin introducciones innecesarias
    • Buscar antes de preguntar era una regla básica de cortesía :)
    • No estoy de acuerdo con la idea de que “es mejor preguntarle a un humano”
      Con los humanos vienen cargas sociales como leer el ambiente, ser juzgado o la competitividad
      Los LLM dan respuestas neutrales y educadas sin esa carga
  • El comportamiento del shell es dependiente del contexto, así que el significado de & cambia según la posición
    Como en IFS=\| read A B C <<< "first|second|third", donde solo se aplica localmente dentro de una línea
    El & al final de la línea significa ejecución en segundo plano, mientras que en medio significa redirección
    Este tipo de patrón es difícil de aprender, pero al final es algo que hay que aprender

  • Esto vuelve a hacerte notar lo antiguos que son los sistemas que usamos
    Manejar file descriptors como números es como darle punteros directamente al usuario
    Sería mejor si existiera un acceso basado en nombres

    • Pero en esa época el usuario era el programador
    • En el destino sí se pueden usar nombres. & cumple la función de indicar que eso no es un archivo sino un descriptor
      < ya estaba en uso para redirección de entrada, así que no podía reutilizarse
    • Es aleccionador ver cómo estas herramientas simples y lógicas se mantienen durante décadas
    • 2>/dev/stdout se parece a 2>&1, pero no es exactamente lo mismo
      /dev/stdout es un acceso basado en nombres más familiar
    • A mí, de hecho, me gusta esta simplicidad anticuada del shell
      Un script de hace 15 años sigue funcionando igual hoy
  • La redirección es una función realmente fascinante
    Por ejemplo, uso con frecuencia la sustitución de procesos como en diff <(seq 1 20) <(seq 1 10)

    • Pero es una pena que las herramientas Unix no den mejor soporte a los file descriptors
      Sería mucho más potente poder pasar archivos, streams o sockets directamente a un proceso
      Si Bash pudiera abrir sockets directamente y pasarlos a otros programas, el sandboxing también sería más fácil
      [^1]: Existe /dev/tcp, pero su funcionalidad es limitada
    • Aun así, la expresión “redirección de archivos” es un poco engañosa
      En realidad se implementa con una named pipe, así que no permite seek
      Por eso Zsh agregó la sintaxis =(command) que usa un archivo temporal
  • Yo entendía 2>&1 memorizándolo como “el 2 entra en la dirección del 1”

  • Sobre ‘2>&1’ y la redirección en profundidad, están estos textos
    Understanding Linux's File Descriptors: A Deep Dive Into '2>&1' and Redirection
    Enlace a la discusión relacionada

    • En las entrevistas siempre consulto Essential System Administration de O’Reilly
      Enlace al libro