1

I have this script:

while read $item;
do
    # Some bash logic here
done <<< "$({ cat /path/to/some/file; echo; })"

Now I want to also use find to find the name of some directories, and pass that alongside the cat to the while loop.

In other words, I want to:

  • cat a file
  • find some directories
  • Concatenate the results
  • Feed them as here-document to the while loop

I'm stuck at this point.

I though of duplicating the while logic, which is not a good method. I also thought of reusing the logic inside the while loop using functions.

However, concatenating stuff in here-document might seem to be the correct way to do it.

3
  • 2
    Putting the clunkiness and limitations of <<< "$(…)" aside, a note: you already concatenate the output of cat and the output of echo. Sole echo prints a newline and it's futile here because $() removes all trailing newlines (and then <<< adds exactly one). My point is you already concatenate the results of two commands. :) Commented Feb 24, 2023 at 13:13
  • @KamilMaciorowski, I guess that's the result of copy/pasting codes without truly understanding them. Somewhere I got that code and it worked. :D Commented Feb 24, 2023 at 14:22
  • Getting the expected output from some specific set of sample input from any code doesn't mean that code "works", it just means it didn't fail for that test case. Don't use code you don't understand as there'll probably be cases not present in whatever sample data you tested with that come back to bite you later when run on your (or your customers'!) real data.
    – Ed Morton
    Commented Feb 27, 2023 at 15:13

1 Answer 1

5

Actually <<< "$({ cat /path/to/some/file; echo; })" is a here-string containing a quoted command substitution rather than a here-document. As Kamil Maciorowski has already pointed out, you already know how to concatenate the results of the two commands cat /path/to/some/file and echo inside the command substitution, and you could do the same with cat and find:

... <<< "$(cat /path/to/some/file; find . -name '*foo*')"

I omitted the inner { ... } since the commands are already grouped by $( ... ).

However it would be more natural IMHO to use process substitution to concatenate the outputs. To see how that works, start from simple input redirection

while IFS= read -r item
do
    # Some bash logic here
done < /path/to/some/file

which redirects the contents of the file to the loop via stdin; then

while IFS= read -r item
do
    # Some bash logic here
done < <(cat /path/to/some/file)

which converts the output of cat /path/to/some/file to a pseudo-file that you can redirect in the same way. Now it's a simple matter to add another stdout-generating command to the process list:

while IFS= read -r item
do
    # Some bash logic here
done < <(cat /path/to/some/file; find . -name '*foo*')

See for example

Note that in all cases, the syntax is read item not read $item.

2
  • Thank you so much for teaching me. May I ask why should I not use here-string? Commented Feb 25, 2023 at 6:19
  • @SaeedNeamati I've updated the answer with additional explanation and references Commented Feb 25, 2023 at 13:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .