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
.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With