Как передать вывод команды другим командам?

Пример:

ls | echo ничего не печатает (на самом деле пустая строка). Я бы ожидал, что он напечатает список файлов.

ls | grep 'foo', с другой стороны, работает так, как ожидалось (печатает файлы с 'foo' в их названии).

Что я делаю в таких ситуациях, это что-то вроде: ls | while read OUT; do echo $OUT; done но это довольно громоздко.

Почему конвейер работает с некоторыми командами, но не с другими? Как я могу обойти эту проблему?