Una buena manera de detectar la diferencia entre ellos es experimentar un poco en la línea de comando. A pesar de la similitud visual en el uso del <
personaje, hace algo muy diferente a una redirección o canalización.
Usemos el date
comando para probar.
$ date | cat
Thu Jul 21 12:39:18 EEST 2011
Este es un ejemplo inútil, pero muestra que cat
aceptó la salida de date
STDIN y la volvió a escupir. Los mismos resultados se pueden lograr mediante la sustitución del proceso:
$ cat <(date)
Thu Jul 21 12:40:53 EEST 2011
Sin embargo, lo que sucedió detrás de escena fue diferente. En lugar de recibir una transmisión STDIN, en cat
realidad se le pasó el nombre de un archivo que necesitaba abrir y leer. Puede ver este paso utilizando en echo
lugar de cat
.
$ echo <(date)
/proc/self/fd/11
Cuando cat recibió el nombre del archivo, leyó el contenido del archivo. Por otro lado, echo solo nos mostró el nombre del archivo que se pasó. Esta diferencia se vuelve más obvia si agrega más sustituciones:
$ cat <(date) <(date) <(date)
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011
$ echo <(date) <(date) <(date)
/proc/self/fd/11 /proc/self/fd/12 /proc/self/fd/13
Es posible combinar la sustitución del proceso (que genera un archivo) y la redirección de entrada (que conecta un archivo a STDIN):
$ cat < <(date)
Thu Jul 21 12:46:22 EEST 2011
Se ve más o menos igual, pero esta vez a cat se le pasó la transmisión STDIN en lugar de un nombre de archivo. Puedes ver esto probándolo con echo:
$ echo < <(date)
<blank>
Como echo no lee STDIN y no se pasó ningún argumento, no obtenemos nada.
Las canalizaciones y las redirecciones de entrada introducen contenido en la secuencia STDIN. La sustitución de procesos ejecuta los comandos, guarda su salida en un archivo temporal especial y luego pasa ese nombre de archivo en lugar del comando. Cualquier comando que esté usando lo trata como un nombre de archivo. Tenga en cuenta que el archivo creado no es un archivo normal, sino una tubería con nombre que se elimina automáticamente una vez que ya no es necesario.
[[ -p <(date) ]] && echo true
. Esto producetrue
cuando lo ejecuto con bash 4.4 o 3.2.Supongo que está hablando de
bash
algún otro shell avanzado, porque el shell posix no tiene sustitución de proceso .bash
informes de la página del manual:En otras palabras, y desde un punto de vista práctico, puede usar una expresión como la siguiente
como nombre de archivo para otros comandos que requieren un archivo como parámetro. O puede usar la redirección para dicho archivo:
Volviendo a su pregunta, me parece que la sustitución de procesos y las tuberías no tienen mucho en común.
Si desea canalizar en secuencia la salida de varios comandos, puede utilizar uno de los siguientes formularios:
pero también puede usar la redirección en la sustitución del proceso
finalmente, si
command3
acepta un parámetro de archivo (en sustitución de stdin)fuente
Aquí hay tres cosas que puede hacer con la sustitución de procesos que de otra manera serían imposibles.
Múltiples entradas de proceso
Simplemente no hay forma de hacer esto con tuberías.
Preservando STDIN
Digamos que tiene lo siguiente:
Y quieres ejecutarlo directamente. Lo siguiente falla miserablemente. Bash ya está utilizando STDIN para leer el script, por lo que otra entrada es imposible.
Pero de esta manera funciona perfectamente.
Sustitución de proceso de salida
También tenga en cuenta que la sustitución de procesos también funciona a la inversa. Entonces puedes hacer algo como esto:
Ese es un ejemplo un poco complicado, pero envía stdout a
/dev/null
, mientras canaliza stderr a un script sed para extraer los nombres de los archivos para los que se mostró un error de "Permiso denegado", y luego envía LOS resultados a un archivo.Tenga en cuenta que el primer comando y la redirección stdout están entre paréntesis ( subshell ) para que solo se envíe el resultado de ESE comando
/dev/null
y no se meta con el resto de la línea.fuente
diff
ejemplo es posible que desee que se preocupan por el caso en que elcd
puede fallar:diff <(cd /foo/bar/ && ls) <(cd /foo/baz && ls)
.Si un comando toma una lista de archivos como argumentos y procesa esos archivos como entrada (o salida, pero no comúnmente), cada uno de esos archivos puede ser una tubería con nombre o un pseudoarchivo / dev / fd proporcionado de forma transparente por la sustitución del proceso:
Esto "canalizará" la salida de los tres comandos para ordenar, ya que ordenar puede tomar una lista de archivos de entrada en la línea de comandos.
fuente
<()
, como muchas funciones avanzadas de shell, originalmente era una función ksh y fue adoptada por bash y zsh.psub
es específicamente una función de peces, nada que ver con POSIX.Cabe señalar que la sustitución del proceso no se limita al formulario
<(command)
, que utiliza la salida decommand
como un archivo. También puede tener el formato>(command)
que alimenta un archivo como entradacommand
. Esto también se menciona en la cita del manual bash en la respuesta de @ enzotib.Para el
date | cat
ejemplo anterior, un comando que usa la sustitución de proceso del formulario>(command)
para lograr el mismo efecto sería,Tenga en cuenta que lo
>
anterior>(cat)
es necesario. Esto puede ser nuevamente ilustrado claramenteecho
como en la respuesta de @ Caleb.Entonces, sin el extra
>
,date >(cat)
sería lo mismodate /dev/fd/63
que imprimirá un mensaje en stderr.Supongamos que tiene un programa que solo toma nombres de archivos como parámetros y no procesa
stdin
nistdout
. Usaré el script simplificadopsub.sh
para ilustrar esto. El contenido depsub.sh
esBásicamente, prueba que sus dos argumentos son archivos (no necesariamente archivos regulares) y, si este es el caso, escriba el primer campo de cada línea
"$1"
para"$2"
usar awk. Entonces, un comando que combina todo lo mencionado hasta ahora es,Esto imprimirá
y es equivalente a
pero lo siguiente no funcionará, y tenemos que usar la sustitución del proceso aquí,
o su forma equivalente
Si
./psub.sh
también se leestdin
además de lo mencionado anteriormente, entonces no existe una forma equivalente, y en ese caso no hay nada que podamos usar en lugar de la sustitución del proceso (por supuesto, también puede usar una tubería con nombre o un archivo temporal, pero ese es otro historia).fuente