Primeiro, o uso de outro cat
não faz muita diferença, e você não deve se preocupar com isso.
Em segundo lugar, os comandos que compõem um pipeline são executados em processos separados, independentemente de serem comandos externos ou internos:
$ a=0
$ a=1 | a=2 | a=3
$ echo $a
0
Quanto ao seu problema exato, não é possível simplesmente conectar 'stdin' a 'stdout'; mesmo se um shell tivesse algum nop
embutido que entraria em colapso quando usado em um pipeline (por exemplo, | nop |
- > |
), o shell não tem como saber de antemão, no momento em que configura o pipeline, que sua "central telefônica" mudará para nop
em vez de awk
ou sort
.
Você também pode obter o mesmo efeito que "painéis de controle", construindo você mesmo o pipeline e chamando eval para executá-lo. Exemplo:
$ cat test.sh
type='file -zi "$1"'
case $type in
*application/gzip*) mycat='zcat "$1"';;
*) mycat='cat "$1"';;
esac
case $type in
*charset=utf-16le*) mycat="$mycat | iconv -f utf16le";;
esac
# highlight comments in blue
esc='printf "\x1b"';
mycat="$mycat | sed 's/^#.*/$esc[34m&$esc[m/'"
echo >&2 "$mycat" # show the built pipeline
eval "$mycat" # ... and run it
$ iconv -t utf16 test.sh > test16.sh; gzip test16.sh
$ sh test.sh test16.sh.gz
Isso é um pouco fora do tópico, mas no Linux existe uma maneira mais rápida de copiar o stdin para stdout (se algum deles é um pipe) - o splice (2) syscall, que não envolve mover os dados de e para a terra do usuário:
$ cat splice_cat.c
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdlib.h>
#include <err.h>
int main(int ac, char **av){
ssize_t r;
size_t block = ac > 1 ? strtoul(av[1], 0, 0) : 0x20000;
for(;;)
if((r = splice(0, NULL, 1, NULL, block, 0)) < 1){
if(r < 0) err(1, "splice");
return 0;
}
}
$ cc -Wall splice_cat.c -o splice_cat
$ dd if=/dev/zero bs=1M count=100 status=none | (time cat >/dev/null)
real 0m0.153s
user 0m0.012s
sys 0m0.056s
$ dd if=/dev/zero bs=1M count=100 status=none | (time ./splice_cat >/dev/null)
real 0m0.100s
user 0m0.004s
sys 0m0.020s
No entanto (afaik), isso não é usado nem pelo shell nem pelo cat
, dd
, etc.