This question already has answers here:
Difference in pipe and file redirection - BASH
(3 answers)
What is a simple explanation for how pipes work in Bash?
(11 answers)
Piping and Redirection
(5 answers)
Closed 2 years ago.
Here is something I don't understand.
Why this works : echo "akka" | cat
But this does not produce "akka" on the console : echo "akka" > cat
And this does not even work : cat < echo "akka"
For me they should be the same. But these 3 commands seem different
You are confusing the differences between file redirection and piping.
The pipe symbol | is used to pass the output of one command into another command.
Meanwhile, < and > are used for file redirection.
These are very different operations.
Example 1:
echo "akka" | cat
The echo command has the output akka, and this is piped into the standard input of the cat command. The cat command writes to standard output, so in this case it prints akka. Of course, this is no different from doing simply:
echo "akka"
Example 2:
echo "akka" > cat
The echo command has the output akka. Using >, this output is then redirected into a file called cat. There is no output shown in the terminal in this case, since the output is placed into a file instead.
Example 3:
cat < echo "akka"
This is quite different from the first two. This runs the cat command, which reads from standard input. Using <, input is passed to the cat command from a file called echo. If no such files exists, then it will produce an error.
Related
This question already has answers here:
Two redirection operators in one command
(5 answers)
Closed 8 months ago.
I am working on an program related to shell commands.
I want to make that, when the user enter an command, this not show any output.
I have tried adding > /dev/null to the command, this works well for commands like
$ echo "some text" | sudo tee some.txt > /dev/zero
$ cat some.txt
some text
But if the user enter a command with append (>>), the new line is not added as expected
$ echo "appending another line" >> some.txt > /dev/zero
$ cat some.txt
some text
I understood that the commands were executed from left to right, something escapes me
if the user enter a command with append (>>), the new line is not added as expected
The redirections, are executed left to right. >>some.txt redirects stdout to some.txt, then >/dev/null overwrites that redirection and redirects stdout to /dev/null. Then the command is executed and the output of echo command is redirected to /dev/null.
This question already has answers here:
Useless use of cat?
(9 answers)
Piping and Redirection
(5 answers)
Closed 3 years ago.
What is the difference between the statement cat a.txt | wc and the statement wc < cat a.txt. In both cases, isn’t the output of cat a.txt being directed into wc?
Absolutely not. In your second case (wc < cat a.txt) you are invoking the command wc a.txt while connecting a file named cat to the standard input of the process.
It might seem confusing, but most shells allow you to redirect the input anywhere in the command line.
wc a.txt < cat
would be the same as (the arguably more confusing)
wc < cat a.txt
To redirect the output of a command to the input of another, you use the pipe character. To invoke a command with a file as its standard input, you use the chevrons.
Now, modern shells will let you type commands like this one:
wc <(cat a.txt)
This is called process substitution and is not exactly the same thing as either of the two methods you were asking about. In this case, the shell will invoke the process cat a.txt and "catch" its output in a file descriptor. Then, the shell will invoke the "main" command (wc) and pass a reference to that file descriptor as an argument, as if it were a file name. It enables a command that expects a simple file name to read the output of an ad hoc command.
This question already has answers here:
Bash here document produces no output, any idea why?
(2 answers)
Closed 5 years ago.
I am trying to understand the bash's here document feature. Below code works as expected and returns "abc" to terminal. If I replace the program cat by echo I do not see any output. Why I am not able to pass here document to echo ? Is it becuase it is a bash builtin ?
cat <<EOF
abc
EOF
"abc" is output to the terminal as expected.
No output for below comamnd though-
echo <<EOF
abc
EOF
You want:
cat <<EOF
abc
EOF
Otherwise, what you're doing is just running echo with its stdin connected to a temporary file having abc in it. Since echo doesn't read stdin, it never finds out if there's contents waiting to be read from there or not.
This question already has answers here:
How can I use a file in a command and redirect output to the same file without truncating it?
(14 answers)
Closed 5 years ago.
I need to put some environment variables values to file.
cat file
# $VAR
echo $VAR
# text
When I do envsubst '$VAR $VAR' < file > file file becomes empty. To resolve this issue I use envsubst '$VAR $VAR' < file | tee file 2>&1 >/dev/null. But sometimes it doesn't work, I mean file becomes empty. The first question is why sometimes file becomes empty and the second is what is the TRUE Unix way to put env vars to file in Linux and *BSD and MacOS ?
The shell always processes the output redirection, which truncates the file, before starting the command.
With the pipeline envsubst ... < file | tee file, the two commands envsubst and tee run asynchronously, which means the OS is free to start one or the other command first. You are basically tossing the dice that envsubst runs and reads file before tee runs and truncates the file.
The only correct solution is to write to a temporary file, then replace the original with the temporary file after you have confirmed that the command was successful.
This question already has answers here:
How to pass command output as multiple arguments to another command
(5 answers)
Closed 5 years ago.
When I run the following Bash script, I would expect it to print Hello. Instead, it prints a blank line and exits.
echo 'Hello' | echo
Why doesn't piping output from echo to echo work?
echo prints all of its arguments. It does not read from stdin. So the second echo prints all of its arguments (none) and exits, ignoring the Hello on stdin.
For a program that reads its stdin and prints that to stdout, use cat:
$ echo Hello | cat
Hello
In this case the pipe you are using are more correctly known as anonymous pipes, because they have no name (there are also named pipes). Anonymous pipes only work between related processes, for example processes with the same parent.
Pipes are part of the IO system resulting from the C runtime-library. These streams are buffered (there is an exception) by default. Basically a pipe is just connecting the output buffer from one process to the input buffer of another.
The first three streams used (called file descriptors) are numbered 0, 1, and 2. The first, 0, is known as standard input, or stdin (the name used in C). By default this is connected to the keyboard, but it can be redirected either using the < symbol or the program name being on the right side of a pipe.
The second, 1, is known as standard output, or stdout. By default this is connected to the terminal screen, but can be redirected by using the > symbol or the program name being on the left side of a pipe.
So:
echo 'Hello' | echo
takes the standard output from echo and passes it to the standard input of echo. But echo does not read stdin! So nothing happens.
Filter programs process the filenames specified on the command-line. If no filenames are given then they read stdin. Examples include cat, grep, and sed, but not echo. For example:
echo 'Hello' | cat
will display 'Hello', and the cat is useless (it often is).
echo 'Hello' | cat file1
will ignore the output from echo and just display the contents of file1. Remember that stdin is only read if no filename is given.
What do you think this displays?
echo 'Hello' | cat < file1 file2
and why?
Finally, the third stream, 2, is called standard error, or stderr, and this one is unbuffered. It is ignored by pipes, because they only operate between stdin and stdout. However, you can redirect stderr to use stdout (see man dup2):
myprog 2>&1 | anotherprog
The 2>&1 means "redirect file descriptor 2 to the same place as fie descriptor 1".
The above is normal behaviour, however a program can override all that if it wants to. It could read from file descriptor 2, for example. I have omitted a lot of other detail, including other forms of redirection such as process substitution and here documents.
Piping can be done only for commands taking inputs from stdin. But echo does not takes from stdin. It will take input from argument and print it. So this wont work. Inorder to echo you can do something like echo $(echo 'hello')
It is because echo (both builtin and /bin/echo) don't read anything from stdin.
Use cat instead:
echo 'Hello' | cat
Hello
Or without pipes:
cat <<< 'Hello'