Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I execute command for each stdin line?

Tags:

bash

I've got the following command:

$ cmd-a | while read -r line; do echo "${line}"; cmd-b; done

This works well, and will for all intents and purposes look like cmd-a is just printing its stdout as normal, but for each line we execute cmd-b as well.

Is there a cleaner way to do this?

cmd-a | xargs -n1 cmd-b would be nice, but it splits on all whitespace (I know GNU xargs has the -d option, but it's unfortunately not available to me,) and would suppress the output of cmd-a.

like image 342
Marcus Stade Avatar asked Nov 15 '16 15:11

Marcus Stade


People also ask

What is stdin command?

stdin − It stands for standard input, and is used for taking text as an input. stdout − It stands for standard output, and is used to text output of any command you type in the terminal, and then that output is stored in the stdout stream. stderr − It stands for standard error.


1 Answers

The existing proposal is entirely idiomatic and clean; BashFAQ #001 advises precisely the same mechanism to iterate over input line-by-line. There's no reason to replace it, but if you're using it frequently, it may make sense to encapsulate it.

Consider the following function:

for_each_line() {
  while IFS= read -r line; do
    printf '%s\n' "$line"
    line=$line "$@"
  done
}

...thereafter run as:

cmd-a | for_each_line cmd-b

...or, if your cmd-b is a function and you want it to be able to modify shell state, the above can be invoked as follows (per BashFAQ #24):

for_each_line cmd-b < <(cmd-a)

...which will make the preceding line available to cmd-b in the environment, should it have any reason to modify its behavior based on the value of same.

like image 146
Charles Duffy Avatar answered Oct 10 '22 19:10

Charles Duffy