piping in linux - shell

i have a file called test which contains the word "hello" in it.
shouldn't
echo test | cat
output hello? since its taking the output from the echo test, which is test, as the input for cat. so essentially im doing cat test.
but the actual output is test, im really confused.

Your pipes sends test to cat as the input, not as the argument. You could do:
cat `echo test`
to control the argument to cat with echo.

echo prints its arguments. cat prints a file which is by default standard input. When you pipe echo's standard output is connected to cat's standard input.
Correct is simply cat test.

From cat --help
If no FILE or when FILE is -, read standard input.
In your case, cat reads from stdin, which is test and outputs that.

In some cases you might want the argument to be passed through the pipe. This is how you would do that:
echo test | xargs cat
which will output the contents of the file named "test".

Related

Piping not working with echo command [duplicate]

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'

automatically send stdin to interactive bash script

I have a compiled program which i run from the shell; as i run it, it asks me for an input file in stdin. I want to run that program in a bash loop, with predefined input file, such as
for i in $(seq 100); do
input.txt | ./myscript
done
but of course this won't work. How can I achieve that? I cannot edit the source code.
Try
for i in $(seq 100); do
./myscript < input.txt
done
Pipes (|) are inter-process. That is, they stream between processes. What you're looking for is file redirection (e.g. <, > etc.)
Redirection simply means capturing output from a file, command,
program, script, or even code block within a script and sending it as
input to another file, command, program, or script.
You may see cat used for this e.g. cat file | mycommand. Given the above, this usage is redundant and often the winner of a 'Useless use of cat' award.
You can use:
./myscript < input.txt
to send content of input.txt on stdin of myscript
Based on your comments, it looks like myscript prompts for a file name and you want to always respond with input.txt. Did you try this?
for i in $(seq 100); do
echo input.txt | ./myscript
done
You might want to just try this first:
echo input.txt | ./myscript
just in case.

Significance of echo Start|cat>>log in bash

Can anyone help me out with the following code snippet -
echo Start|cat>>log
When I tried
echo Start>>log
it gave the same output to the log file. Can anyone explain the difference between the two commands?
cat is one of those programs that can take an argument and use it, or just use its standard input if you don't provide an argument. In other words, while:
cat xyzzy
will open the file xyzzy and output its contents, the command:
cat
on its own will read its standard input and send that to standard output.
Hence piping some output through cat without an argument is no different that just sending the output without cat, other than creating a superfluous process. In other words, these two are functionally identical:
echo xyzzy | cat
echo xyzzy
You can use either but the latter (for both my example above and in your question) will use one less process and a few less keystrokes. The cat filter on its own will simply pass the data through as-is and hence is not necessary.

How to wrap piped input to stdout in a bash script?

I want to write a bash script that will wrap piped input with some text.
Based on Googling and trying to pick from examples.
Here is what I have so far, that does not work:
#!/bin/sh
if readlink /proc/$$/fd/0 | grep -q "^pipe:"; then
echo "{ "template":{"name":"contact sheet template","root":"root","parameters": ["pages"]},"pages":"
cat
echo "}"
fi
I am receiving a JSON list from another program as piped input and I want to output before and afterwards with the above text before I pipe the results to the next program.
program_1 | wrapper.sh | program_2 > outputfile
But it doesn't output anything.
Can someone with more bash expertise point me in the right direction?
Personally I'll search in this way :
myscript.sh
echo 'BEFORE' $(cat) 'AFTER'
Do you mean your script is reading standard input from a pipe, such as
$ other-process | my-script
?
Then the commands in your script will simply inherit standard input from the pipe
#!/bin/sh
# Output preamble
cat <<EOF
{ "template":{"name":"contact sheet template","root":"root","parameters": ["pages"]},"pages":
EOF
cat # This reads from standard input inherited from your script
# Output the closing
cat <<EOF
}
EOF

Why this echo construct does not work?

When I do this:
$ /bin/echo 123 | /bin/echo
I get no o/p. Why is that?
You ask why it doesn't work. In fact, it does work; it does exactly what you told it to do. Apparently that's not what you expected. I think you expected it to print 123, but you didn't actually say so.
(Note: "stdin" is standard input; "stdout" is standard output.)
/bin/echo 123 | /bin/echo
Here's what happens. The echo command is executed with the argument 123. It writes "123", followed by a newline, to its stdout.
stdout is redirected, via the pipe (|) to the stdin of the second echo command. Since the echo command ignores its stdin, the output of the first echo is quietly discarded. Since you didn't give the second echo command any arguments, it doesn't print anything. (Actually, /bin/echo with no arguments typically prints a single blank line; did you see that?)
Normally pipes (|) are used with filters, programs that read from stdin and write to stdout. cat is probably the simplest filter; it just reads its input and writes it, unchanged, to its output (which means that some-command | cat can be written as just some-command).
An example of a non-trivial filter is rev, which copies stdin to stdout while reversing the characters in each line.
echo 123 | rev
prints
321
rev is a filter; echo is not. echo does print to stdout, so it makes sense to have it on the left side of a pipe, but it doesn't read from stdin, so it doesn't make sense to use it on the right side of a pipe.
"echo" reads from command line, not standard input. So pipeline is not working here.
From bash manual:
echo [-neE] [arg ...]
Output the args, separated by spaces, terminated with a newline.
So your first echo did print "123" to stand output, however, the second echo didn't make use of it so "123" is dropped. Then an empty line is printed as if you run "echo".
You can use cat as Keith Thompson suggested:
echo 123|cat
/bin/echo 123 < /bin/echo
the pipe = concate
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-4.html
Pipes let you use the output of a program as the input of another one

Resources