En ambos
<file.txt tee >(grep LITERAL) >(wc -l) >/dev/null
Y:
{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1
Todos tee, grepy wcse inician simultáneamente. Lo que importa es lo que sucede al final.
wcsolo imprimirá el resultado cuando vea el final del archivo en su entrada estándar. En el primer caso, es cuando teesale, porque luego teese cerrará fden el otro extremo de la tubería que wcestá leyendo (iniciado por la sustitución del proceso). No hay garantía de que grephabrá leído toda su entrada para ese momento, y mucho menos escrito su salida (dado que las tuberías pueden contener una gran cantidad de datos y que wcprobablemente sea más rápido que grep)
En el segundo caso, wcveremos el final del archivo cuando todos los escritores en la tubería desde la que está leyendo hayan cerrado su extremo de la tubería. En ese caso, sin embargo, hay varios escritores. tee(a través de su fd abierto /dev/fd/3y a través de su fd 3) y grepque también tiene sus fd3 abiertos a la tubería wc(aunque no lo está utilizando, y mucho menos escribirle). El interno {probablemente causará un proceso de subshell adicional que también tendrá un fd3 abierto y esperará a ambos teey grep.
Eso significa que wcsolo escribirá su número de línea después de grephaber salido.
Si lo hubiera escrito de la manera correcta, es al cerrar los archivos que no necesitaban abrirse:
{ { <file.txt tee /dev/fd/3 4>&- |
grep LITERAL >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
Entonces el pedido no se habría garantizado en shells que optimizan el proceso de subshell. Sin embargo, el único shell que sé que sí es, ksh93pero ksh93usa pares de conectores para tuberías, por /dev/fd/3lo que no funcionará allí en Linux al menos.
Para ver qué procesos se están ejecutando, puede reemplazar grepcon ps:
$ { { <file.txt tee /dev/fd/3 4>&- | ps -H >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1
PID TTY TIME CMD
8727 pts/5 00:00:00 bash
8815 pts/5 00:00:00 bash
8817 pts/5 00:00:00 tee
8818 pts/5 00:00:00 ps
8816 pts/5 00:00:00 wc
Con bash, puede ver ese proceso de shell adicional, y puede ver que también tiene la tubería abierta en fd 3 con:
$ (p=$BASHPID; { { <file.txt tee /dev/fd/3 4>&- | lsof -ag "$p" -d3 >&4 3>&- 4>&-; } 3>&1 | wc -l 4>&-;} 4>&1)
COMMAND PID PGID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 9843 9842 chazelas 3w FIFO 0,8 0t0 153304 pipe
tee 9845 9842 chazelas 3w FIFO 0,8 0t0 153304 pipe
lsof 9846 9842 chazelas 3r DIR 0,3 0 1 /proc
grep LITERAL >&4 3>&- 4>&-significa que el fd 4 parece ser usado y cerrado?>&4, abreviatura de1>&4,grepfd 1 y 4 apuntan al mismo recurso (el stdout inicial del shell).grepno necesita tener su fd 4 abierto a nada. No hace nada con él, así que lo4>&-Para obtener un pedido predecible use
fuente