In bash, an empty command with a redirection just opens the file in the manner associated with the redirection and then closes it*.
echo "hello" >&0 | > file.txt is a compound command composed of two simple commands
echo "hello" >&0 ,
> file.txt , piped. The second command is empty, so bash just opens the file for writing, truncating it, and then closes it.
In a terminal, usually the standard input, output and error are all connected to the terminal. So when you redirect stdout to stdin, it’s still pointing to the terminal, and the output of
echo hello >&0 is seen in the terminal, and is not sent to the pipe at all.
In zsh, an empty command with a redirection defaults to having
cat be the command. So
echo "hello" >&0 | > file.txt is effectively
echo "hello" >&0 | cat > file.txt , and you will see the effect you want. This is not possible in bash. Here, you’ll see another redirection feature not seen in bash: when you redirect the output of a command multiple times, the output is send to each of those redirected destinations (so the
hello is send both to the terminal and to the pipe). In bash, it’s only send to the last redirected location.