5

I am learning about basic terminal commands.

Why is this command not working as I expect it to?

echo "hello" >&0 | > file.txt

I know I can simply type echo "hello" > file.txt but I am learning about using pipes. I just want to output the word"hello" to a file.

16

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.


* The exception being command substitution with redirected stdin. In $(<some-file), bash will read the contents of some-file and use it as the value of the command substitution.

| improve this answer | |
  • and in echo "hello" >&0 | cat > file.txt in Bash, it's the >&0 redirection that is processed last, so the output goes to the terminal (and only there) – ilkkachu Mar 28 '18 at 19:38
12

Ah I see what you were thinking (I think). You tried

echo hello | > file

and nothing happened to file, so you thought, maybe I need to turn my command's output into stdin by redirecting:

echo hello >&0 

But turning stdout into stdin is exactly what a pipe does. It takes stdout and passes it to the command on its right as stdin. If you redirect stdout, nothing will get through the pipe:

$ echo hello >&0 | cat > file
hello
$ cat file
$

(nothing there)

But hello came out in the terminal, which is reading from stdin as usual:

$ cat /dev/fd/0
hi
hi
I am talking to myself!
I am talking to myself!

and so on...

If we don't redirect...

$ echo hello | cat > file
$ cat file
hello

stdout of echo hello went through the pipe (instead of to the terminal) and became stdin of cat.

So, the pipe does what you wanted to do (turn stdout into stdin and connect it to the right command) and you don't have to do that yourself by fiddling with file descriptors.

As for why an empty command with redirection doesn't do what you want, see muru's answer.

| improve this answer | |
6

I guess that you want to write the output to file and stdout too.

echo hello > file.txt 

does that partially, but it skips the standard output (prints nothing to the console). If you want that too, use the tee command as below:

echo hello | tee file.txt

It pipes the output of echo to the input of tee, and then tee writes to the screen and into the file.txt too.

If you just want to print to file use cat command as below:

echo hello | cat >file.txt

Also check this answer for how redirects work: https://stackoverflow.com/a/818265/5771279

and this for how pipe works: https://stackoverflow.com/a/9834118/5771279

Take a look on the man page of tee command too.

| improve this answer | |
  • I just want to write to file.Why does this command do nothing : echo hello | >file.txt – Prof-Wiz Mar 28 '18 at 12:14
  • 1
    it does :), writes the output to file. In this particular example it just clears the file and writes nothing to it. Because the command after the pipe outputs nothing (there is no command) – Levente M Mar 28 '18 at 12:20
  • It was a good read.Did not understand why "echo test >&0" still prints 'test'.The output of echo is going to stdin so nothing should output – Prof-Wiz Mar 28 '18 at 12:47
  • 3
    @Prof-Wiz "output of echo is going to stdin so nothing should output" but as muru's answer states, stdin is connected to your terminal (in a read/write manner), so anything written to stdin is still visible. By contrast echo hello < /dev/null >&0 (where stdin is taken from the "null device", but any file would do) produces an error because stdin has been opened only for reading and cannot be written to. – TripeHound Mar 28 '18 at 14:43
2
  • The > symbol is for file redirection to start of a file.
  • The >> symbol is for file redirection to the end of a file (append).
  • The | symbol is for "piping" or passing the output from one command as input to another command.

    $ echo "Hello" > file.txt
    $ echo "World!" >> file.txt
    $ cat file.txt
    Hello
    World!
    $ cat file.txt | grep !
    World!
    

The grep (Global regular expression print) command searches a file for a given search string and prints the line it is on.

The &>0 according to Advanced-Bash Scripting Guide:

&>filename
  # Redirect both stdout and stderr to file "filename."
  # This operator is now functional, as of Bash 4, final release.

In your case the file name was 0 which is standard input. So it is redirecting all output to input. Which as best as I can tell is a circular reference that will not work. The syntax you used is >&0 which redirects output to input. Which is also appears to be a circular reference.

The "filenames" are:

  • 0 standard input
  • 1 standard output
  • 2 standard error output

The traditional way of using file descriptor 0 (standard input) through file redirection is:

 0< FILENAME
    < FILENAME
      # Accept input from a file.
      # Companion command to ">", and often used in combination with it.
      #
      # grep search-word <filename

If you want to use the echo command and | together (as Zanna's answer points out) you can use:

$ echo "hello" | cat > file.txt
$ cat file.txt
hello
| improve this answer | |
  • You may want to address >&0 as well – Sergiy Kolodyazhnyy Mar 29 '18 at 1:12
  • @SergiyKolodyazhnyy I tried my best but do not think it is that great. 2>&1 has always been my Achilles heel. This is really more your cup of tea and would enjoy reading your answer instead. – WinEunuuchs2Unix Mar 29 '18 at 2:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.