1

Suppose I have a command which outputs a list of strings

string1
string2
string3
.
.
stringN

How can I loop through the output of the list in a shell?

For example:

myVal=myCmd
for val in myVal
  do
    # do some stuff
  end
0

2 Answers 2

5

Use a bash while-loop, the loop can be done over a command or an input file.

while IFS= read -r string
do 
    some_stuff to do
done < <(command_that_produces_string)

With an example, I have a sample file with contents as

$ cat file
My
name
is not 
relevant
here

I have modified the script to echo the line as it reads through the file

$ cat script.sh
#!/bin/bash
while IFS= read -r string
do
    echo "$string"
done < file

produces an o/p when run as ./script.sh

My
name
is not
relevant
here

The same can also be done over a bash-command, where we adopt process-substitution (<()) to run the command on the sub-shell.

#!/bin/bash

while IFS= read -r -d '' file; do
    echo "$file"
done < <(find . -maxdepth 1 -mindepth 1 -name "*.txt" -type f -print0)

The above simple find lists all files from the current directory (including ones with spaces/special-characters). Here, the output of find command is fed to stdin which is parsed by while-loop.

Sign up to request clarification or add additional context in comments.

5 Comments

An excellent answer. The only thing I can find to grumble about is the use of code-formatting (backticks) for things that are technical terms, but not actually code.
See this meta discussion, on-point re: which use cases are and are not appropriate for code-span formatting.
@CharlesDuffy: Really appreciate your time, encouraging my answer! have been learning from the experts over time on how to format answers the best. Will surely correct them in the future.
Oh. Actually, one more quibble -- you might consider avoiding the ABS as a reference; it's often out-of-date, and consistently using bad practices in its examples. Much of what we do in the freenode #bash channel is try to break people of unfortunate habits they picked up using it (in the words of the factoid, "the ABS will teach you to write bugs, not scripts"). The Wooledge BashGuide and the bash-hackers wiki are sources of far better repute.
(Indeed, this answer is of such consistently high quality that I didn't bother to look at the linked references earlier -- I don't often see folks paying attention to corner-cases and details as you are here and using the ABS!)
1

You are very close, can't tell if it is just cut and paste/typos that are causing the issue - note the quotes on line 1 and the $ in line 2.

myVal=`echo "a b c"`
for val in $myVal
do
    echo "$val"
done

7 Comments

This can't distinguish between a line with a b c and a, b and c on three different lines.
it'll also replace a * with a list of files in the current directory.
moreover, if a * being expanded by the in $myVal has a result that itself can be treated as a glob, that'll happen again in echo $val do to the lack of quotes there.
@CharlesDuffy Did you read the question? Replace "echo a b c" for a command that outputs a list of strings. - No mention of commas. No mention of globs. This works perfectly for the case given.
The example given, however, used newlines explicitly. This answer makes assumptions without any foundation for them. As for "no mention of globs" -- that's the point: You're adding behavior (glob expansion) that isn't specified to be desired. Yes, you're adding that behavior because it's present by default in a really badly-designed language (and you're choosing to use constructs that don't bypass those unfortunate defaults, and further choosing not to disable them explicitly), but it's unspecified behavior present in your answer on account of choices under your control nonetheless.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.