LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   ls | echo, I got blank, why can't echo take the 2nd seat in a pipeline? (https://www.linuxquestions.org/questions/linux-newbie-8/ls-%7C-echo-i-got-blank-why-cant-echo-take-the-2nd-seat-in-a-pipeline-503883/)

elinuxqs 11-22-2006 07:10 AM

ls | echo, I got blank, why can't echo take the 2nd seat in a pipeline?
 
I have searched "Linux newbie" for "echo" in titles, but no answer to my question is found.

when I learnt pipeline of Bash, I tried:
ls | echo
, which I would like to see the same result of the "ls".
The output of "ls" is redirected to the 2nd command "echo" and be its argument, that's what I thought.

But the output is blank. If I use:
echo $(ls)
instead, I get what I want, like this,
echo $(ls)
a.txt
b.txt

So, does someone know why echo can't take the output of the previous command in a pipeline?

Thanks
elinuxqs

matthewg42 11-22-2006 07:40 AM

echo doesn't read input from stdin, so you can't pipe data into it. If you want to transform stdin to arguments for echo, use xargs, like this:
Code:

ls | xargs echo
xargs reads input from stdin, and transforms it to a list of arguments which it passes to echo. Now, this isn't a very useful thing to do. The shell will expand * to the list of [non-hidden] files in the current working directory, so you can get the same effect by doing:
Code:

echo *
Note that the shell expands the wild-card to a list before passing the list to the echo command. This is a frequently-held misconception which many people have - that the program (in this case echo) sees the wild-card and expands it itself - this used to happen in DOS, but NOT in Unix shells. The shell pre-expands the wild-card and passes that list to the command. You can force the shell to treat the wild-card as a literal string by quoting it, or escaping it with a backslash:
Code:

echo \*
Which will simply print a * character. Similarly, if you do this:
Code:

ls -l '*'
ls will receive the literal * character. ls doesn't know how to expand the wild-card, and will simply try to list the details of the file with the name *, which probably won't exist, and you'll get a message like this:
Code:

ls: *: No such file or directory
If you want a program which reads stdin and prints what it read to stdout, you're looking for cat
Code:

ls |cat
One last thing to note: piping the output of ls into programs will gave subtly different behaviour from allowing ls to print it's output to the terminal. ls prints in columns when it is outputting to th terminal, but one filename per line when output is re-directed or piped into another program. It also supresses colour output in these cases.

soggycornflake 11-22-2006 11:04 AM

Quote:

Originally Posted by matthewg42
One last thing to note: piping the output of ls into programs will gave subtly different behaviour from allowing ls to print it's output to the terminal. ls prints in columns when it is outputting to th terminal, but one filename per line when output is re-directed or piped into another program. It also supresses colour output in these cases.

However, you can force printing in columns with the -C option and colour with --color=always.

elinuxqs 11-23-2006 01:04 AM

Thank you ^^ matthewg42 and soggycornflake

matthewg42, you're cool.
Bash reference doesn't tell me how echo works, so I was confused.
Thank you.

elinuxqs

matthewg42 11-23-2006 07:54 AM

echo was originally an external command, and that command had/has it's own manual page. Because it is something which tends to be used pretty frequently, and is simple, it was adopted by more modern shells as an internal command (this makes it more efficient to call since there is no spawning of a new process for the external program).

This leads to the rather confusing situation with modern distros where you have both the program in /bin/echo, with it's own manual page, but when you type "echo something" in a bash shell, the bash-internal is used, and the behaviour is sligtly different to that which the manual page describes:
Code:

$ echo --version
--version
$ /bin/echo --version
echo (GNU coreutils) 5.96
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software. You may redistribute copies of it under the terms of
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
There is NO WARRANTY, to the extent permitted by law.

Written by FIXME unknown.

Despite this, the behaviour is close enough that for most uses it doesn't matter. The /bin/echo may still get used. The only example I can think of is if your distro uses a very cut down shell for start-up scripts which doesn't include any un-necessary internals. Ubuntu dapper uses the "dash" shell for init, although I think in this case echo is built-in. Does anyone out there know a shell which is distributed with a common Linux which doesn't have echo built in?

soggycornflake 11-24-2006 08:09 AM

Quote:

The /bin/echo may still get used.
Indeed, it will be used in the xargs example you gave above, since it's exec'd directly as a command, not via a subshell.

matthewg42 11-24-2006 08:25 AM

Quote:

Originally Posted by soggycornflake
Indeed, it will be used in the xargs example you gave above, since it's exec'd directly as a command, not via a subshell.

very good point.


All times are GMT -5. The time now is 11:43 AM.