Buscar..


Sintaxis

  • comando </ ruta / a / archivo # Redirigir la entrada estándar al archivo
  • comando> / ruta / a / archivo # Redirecciona la salida estándar a flie
  • comando file_descriptor> / ruta / a / archivo # Redirecciona la salida de file_descriptor a archivo
  • comando> & file_descriptor # Redirecciona la salida a file_descriptor
  • comando file_descriptor> & another_file_descriptor # Redirigir file_descriptor a another_file_descriptor
  • comando <& file_descriptor # Redirigir file_descriptor a la entrada estándar
  • comando &> / ruta / a / archivo # Redirigir la salida estándar y el error estándar al archivo

Parámetros

Parámetro Detalles
descriptor de archivo interno Un entero.
dirección Uno de > , < o <>
descriptor de archivo externo o ruta & seguido de un entero para el descriptor de archivo o una ruta.

Observaciones

Los programas de la consola UNIX tienen un archivo de entrada y dos archivos de salida (las secuencias de entrada y salida, así como los dispositivos, son tratados como archivos por el sistema operativo). Estos son típicamente el teclado y la pantalla, respectivamente, pero cualquiera o todos pueden redirigirse para venir de, o ir a, un archivo u otro programa.

STDIN es una entrada estándar, y es así como el programa recibe una entrada interactiva. STDIN se le suele asignar el descriptor de archivo 0.

STDOUT es una salida estándar. Todo lo que se emita en STDOUT se considera el "resultado" del programa. STDOUT se suele asignar el descriptor de archivo 1.

STDERR es donde se muestran los mensajes de error. Normalmente, cuando se ejecuta un programa desde la consola, STDERR muestra en la pantalla y no se puede distinguir de STDOUT . STDERR se suele asignar el descriptor de archivo 2.

El orden de redireccionamiento es importante.

command > file 2>&1

Redirige ambos ( STDOUT y STDERR ) al archivo.

command 2>&1 > file

Los redireccionamientos que solamente STDOUT , debido a que el descriptor de archivo 2 se redirige al archivo apuntado por el descriptor de archivo 1 (que no es el archivo file sin embargo, cuando se evalúa la declaración).

Cada comando en una tubería tiene su propio STDERR (y STDOUT ) porque cada uno es un proceso nuevo. Esto puede crear resultados sorprendentes si espera que una redirección afecte a toda la tubería. Por ejemplo, este comando (envuelto para legibilidad):

$ python -c 'import sys;print >> sys.stderr, "Python error!"' \
| cut -f1 2>> error.log

imprimirá "error de Python!" a la consola en lugar del archivo de registro. En su lugar, adjunte el error al comando que desea capturar:

$ python -c 'import sys;print >> sys.stderr, "Python error!"' 2>> error.log \
| cut -f1 

Redireccionando salida estándar

> redirige la salida estándar (también conocida como STDOUT ) del comando actual a un archivo u otro descriptor.

Estos ejemplos escriben la salida del comando ls en el archivo file.txt

ls >file.txt
> file.txt ls

El archivo de destino se crea si no existe, de lo contrario, este archivo se trunca.

El descriptor de redirección predeterminado es la salida estándar o 1 cuando no se especifica ninguno. Este comando es equivalente a los ejemplos anteriores con la salida estándar indicada explícitamente:

ls 1>file.txt

Nota: la redirección es inicializada por el shell ejecutado y no por el comando ejecutado, por lo tanto, se realiza antes de la ejecución del comando.

Redireccionando STDIN

< lee de su argumento derecho y escribe en su argumento izquierdo.

Para escribir un archivo en STDIN debemos leer /tmp/a_file y escribir en STDIN es decir, 0</tmp/a_file

Nota: el descriptor de archivo interno está predeterminado en 0 ( STDIN ) para <

$ echo "b" > /tmp/list.txt
$ echo "a" >> /tmp/list.txt
$ echo "c" >> /tmp/list.txt
$ sort < /tmp/list.txt
a
b
c

Redireccionando tanto STDOUT como STDERR

Los descriptores de archivos como 0 y 1 son punteros. Cambiamos lo que apuntan los descriptores de archivos con la redirección. >/dev/null significa 1 puntos a /dev/null .

Primero, STDERR 1 ( STDOUT ) a /dev/null luego STDERR 2 ( STDERR ) a lo que apunta 1 .

# STDERR is redirect to STDOUT: redirected to /dev/null,
# effectually redirecting both STDERR and STDOUT to /dev/null
echo 'hello' > /dev/null 2>&1
4.0

Esto puede reducirse aún más a lo siguiente:

echo 'hello' &> /dev/null

Sin embargo, esta forma puede ser indeseable en la producción si la compatibilidad del shell es una preocupación, ya que entra en conflicto con POSIX, introduce ambigüedad en el análisis y los shells sin esta característica lo malinterpretarán:

# Actual code
echo 'hello' &> /dev/null
echo 'hello' &> /dev/null 'goodbye'

# Desired behavior
echo 'hello' > /dev/null 2>&1
echo 'hello' 'goodbye' > /dev/null 2>&1

# Actual behavior
echo 'hello' &
echo 'hello' & goodbye > /dev/null

NOTA: &> se sabe que funciona como se desea tanto en Bash como en Zsh.

Redireccionando STDERR

2 es STDERR .

$ echo_to_stderr 2>/dev/null # echos nothing

Definiciones:

echo_to_stderr es un comando que escribe "stderr" en STDERR

echo_to_stderr () {
    echo stderr >&2
}

$ echo_to_stderr
stderr

Anexar vs Truncar

Truncar >

  1. Crear archivo especificado si no existe.
  2. Truncar (eliminar el contenido del archivo)
  3. Escribir en el archivo
$ echo "first line" > /tmp/lines
$ echo "second line" > /tmp/lines

$ cat /tmp/lines
second line

Añadir >>

  1. Crear archivo especificado si no existe.
  2. Adjuntar archivo (escritura al final del archivo).
# Overwrite existing file
$ echo "first line" > /tmp/lines

# Append a second line
$ echo "second line" >> /tmp/lines

$ cat /tmp/lines
first line
second line

STDIN, STDOUT y STDERR explicados

Los comandos tienen una entrada (STDIN) y dos tipos de salidas, salida estándar (STDOUT) y error estándar (STDERR).

Por ejemplo:

STDIN

root@server~# read
Type some text here

La entrada estándar se utiliza para proporcionar entrada a un programa. (Aquí estamos usando la read orden interna para leer una línea de STDIN.)

Repartir

root@server~# ls file
file

La salida estándar se usa generalmente para la salida "normal" de un comando. Por ejemplo, ls lista los archivos, por lo que los archivos se envían a STDOUT.

STDERR

root@server~# ls anotherfile
ls: cannot access 'anotherfile': No such file or directory

El error estándar se usa (como su nombre lo indica) para los mensajes de error. Como este mensaje no es una lista de archivos, se envía a STDERR.

STDIN, STDOUT y STDERR son los tres flujos estándar. Se identifican en el shell por un número en lugar de un nombre:

0 = Estándar en
1 = salida estándar
2 = error estándar

De forma predeterminada, STDIN está conectado al teclado, y tanto STDOUT como STDERR aparecen en el terminal. Sin embargo, podemos redirigir STDOUT o STDERR a lo que necesitemos. Por ejemplo, supongamos que solo necesita la salida estándar y todos los mensajes de error impresos en el error estándar deben suprimirse. Ahí es cuando utilizamos los descriptores 1 y 2 .

Redireccionando STDERR a / dev / null
Tomando el ejemplo anterior,

root@server~# ls anotherfile 2>/dev/null
root@server~#

En este caso, si hay algún STDERR, se redirigirá a / dev / null (un archivo especial que ignora cualquier cosa que se coloque en él), por lo que no obtendrá ninguna salida de error en el shell.

Redirigiendo múltiples comandos al mismo archivo

{
  echo "contents of home directory"
  ls ~
} > output.txt

Utilizando tuberías con nombre

A veces es posible que desee generar algo por un programa e ingresarlo en otro programa, pero no puede usar una canalización estándar.

ls -l | grep ".log"

Usted podría simplemente escribir en un archivo temporal:

touch tempFile.txt
ls -l > tempFile.txt
grep ".log" < tempFile.txt

Esto funciona bien para la mayoría de las aplicaciones, sin embargo, nadie sabrá qué hace tempFile y alguien podría eliminarlo si contiene la salida de ls -l en ese directorio. Aquí es donde una tubería con nombre entra en juego:

mkfifo myPipe
ls -l > myPipe
grep ".log" < myPipe

myPipe es técnicamente un archivo (todo está en Linux), así que hagamos ls -l en un directorio vacío en el que acabamos de crear una tubería:

mkdir pipeFolder
cd pipeFolder
mkfifo myPipe
ls -l

La salida es:

prw-r--r-- 1 root root 0 Jul 25 11:20 myPipe

Observe el primer carácter de los permisos, aparece como una canalización, no como un archivo.

Ahora hagamos algo genial.

Abra un terminal y tome nota del directorio (o cree uno para que la limpieza sea fácil) y haga una tubería.

mkfifo myPipe

Ahora vamos a poner algo en la tubería.

echo "Hello from the other side" > myPipe

Notará que esto cuelga, el otro lado de la tubería todavía está cerrado. Abramos el otro lado de la tubería y dejemos pasar esas cosas.

Abra otro terminal y vaya al directorio en el que se encuentra la tubería (o si lo sabe, prepárelo en la tubería):

cat < myPipe

Notará que después hello from the other side salir el hello from the other side , el programa en el primer terminal termina, al igual que en el segundo terminal.

Ahora ejecuta los comandos a la inversa. Comience con cat < myPipe y luego cat < myPipe eco de algo en él. Todavía funciona, porque un programa esperará hasta que algo se coloque en la tubería antes de terminar, porque sabe que tiene que obtener algo.

Las tuberías con nombre pueden ser útiles para mover información entre terminales o entre programas.

Las tuberías son pequeñas. Una vez lleno, el escritor bloquea hasta que algún lector lee el contenido, por lo que necesita ejecutar el lector y el escritor en diferentes terminales o ejecutar uno u otro en segundo plano:

 ls -l /tmp > myPipe &
 cat < myPipe

Más ejemplos usando tuberías con nombre:

  • Ejemplo 1 - todos los comandos en el mismo terminal / mismo shell

    $ { ls -l && cat file3; } >mypipe &
    $ cat <mypipe    
    # Output: Prints ls -l data and then prints file3 contents on screen
    
  • Ejemplo 2 - todos los comandos en el mismo terminal / mismo shell

    $ ls -l >mypipe &
    $ cat file3 >mypipe &
    $ cat <mypipe
    #Output: This prints on screen the contents of mypipe. 
    

    file3 se muestran los primeros contenidos de file3 y luego se muestran los datos de ls -l (configuración LIFO).

  • Ejemplo 3 - todos los comandos en el mismo terminal / mismo shell

    $ { pipedata=$(<mypipe) && echo "$pipedata"; } &
    $ ls >mypipe 
    # Output: Prints the output of ls directly on screen 
    

    $pipedata cuenta que la variable $pipedata no está disponible para su uso en el terminal principal / shell principal, ya que el uso de & invoca una subshell y $pipedata solo estaba disponible en esta subshell.

  • Ejemplo 4 - todos los comandos en el mismo terminal / mismo shell

    $ export pipedata
    $ pipedata=$(<mypipe) &
    $ ls -l *.sh >mypipe
    $ echo "$pipedata"   
    #Output : Prints correctly the contents of mypipe
    

    Esto imprime correctamente el valor de la variable $pipedata en el shell principal debido a la declaración de exportación de la variable. El terminal principal / shell principal no se bloquea debido a la invocación de un shell de fondo ( & ).

Imprimir mensajes de error a stderr

Los mensajes de error generalmente se incluyen en un script para fines de depuración o para proporcionar una experiencia de usuario enriquecida. Simplemente escribiendo un mensaje de error como este:

cmd || echo 'cmd failed'

Puede funcionar para casos simples pero no es la forma habitual. En este ejemplo, el mensaje de error contaminará la salida real de la secuencia de comandos al mezclar los errores y la salida exitosa en la salida stdout .

En resumen, el mensaje de error debe ir a stderr no a stdout . Es bastante simple:

cmd || echo 'cmd failed' >/dev/stderr

Otro ejemplo:

if cmd; then
    echo 'success'
else
    echo 'cmd failed' >/dev/stderr
fi

En el ejemplo anterior, el mensaje de éxito se imprimirá en la stdout mientras que el mensaje de error se imprimirá en stderr .

Una mejor manera de imprimir un mensaje de error es definir una función:

err(){
    echo "E: $*" >>/dev/stderr
}

Ahora, cuando tienes que imprimir un error:

err "My error message"

Redireccionamiento a direcciones de red

2.04

Bash trata algunas rutas como especiales y puede hacer algunas comunicaciones de red escribiendo a /dev/{udp|tcp}/host/port . Bash no puede configurar un servidor de escucha, pero puede iniciar una conexión, y para TCP puede leer al menos los resultados.

Por ejemplo, para enviar una solicitud web simple uno podría hacer:

exec 3</dev/tcp/www.google.com/80
printf 'GET / HTTP/1.0\r\n\r\n' >&3
cat <&3

y los resultados de la página web predeterminada de www.google.com se imprimirán a la stdout estándar.

similar

printf 'HI\n' >/dev/udp/192.168.1.1/6666

enviaría un mensaje UDP que contenga HI\n a un oyente en 192.168.1.1:6666



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow