$(...) é a substituição de comando. Você não quer que a saída de zfs send seja tomada como um nome de arquivo para nc ler. Você deseja enviar a saída de zfs send como entrada para pigz , enquanto pigz envia sua saída para netcat , portanto:
zfs send -R "$zpool@label" | pigz | netcat "$remote_upload_address" "$remote_port"
Não use o UDP. UDP, ao contrário do TCP, não oferece garantia de entrega.
Se você quiser usar o operador de redirecionamento < , poderá usar a substituição ksh -style processo (também encontrada em zsh e bash ):
netcat "$remote_upload_address" "$remote_port" < <(
zfs send -R "$zpool@label" | pigz)
Mas isso não tem vantagem sobre o equivalente padrão | . Lá, o nome do arquivo passado ao operador de redirecionamento < é um canal nomeado ou /dev/fd/x especial que aponta para um canal ( pigz escrevendo na outra extremidade do canal).
É o mesmo, mas envolve algumas chamadas extras ao sistema. Outra diferença é que o shell não espera pelo comando zfs send|pigz (embora espere por netcat , que provavelmente não terminará antes de pigz quando estiver lendo sua saída).
Ou use o operador de redirecionamento de processo de yash :
netcat "$remote_upload_address" "$remote_port" <(
zfs send -R "$zpool@label" | pigz)
Mais uma vez, não há vantagem sobre a sintaxe padrão aqui. Você normalmente usaria o redirecionamento de processo em yash quando quiser ter vários fds de um comando conectado a pipes para outros comandos.