Cat files in subfolders in order given by a list

You have the order in a list, so don't match the filenames with a filename globbing pattern. Instead, construct the names from the strings read from the list:

#!/bin/sh

while read -r name; do
    cat "x/$name/$name.pest"
done <y/list >concatenated.pest

This would concatenate all the relevant .pest files and create a single file called concatenated.pest from these in the current directory, in the order read from y/list.

With a bit of checking included:

#!/bin/sh

while read -r name; do
    pathname="x/$name/$name.pest"

    if [ ! -f "$pathname" ]; then
        printf 'Can not find %s\n' "$pathname"
        echo 'Output file will be incomplete'
        exit 1
    fi >&2

    cat "$pathname"
done <y/list >concatenated.pest

To answer the follow-up subtly different question:

I'm still wondering how would be if my subdirectories didn't have same names as in list though....

Let's make some assumptions:

  • All the subdirectories of x are fair game.
  • All .pest files are fair game.
  • If you have two .pest files with the same name (but in different directories), you don't care what order those two files will be cated in.

Then you have:

while read -r name; do
    cat x/*/"$name.pest"
done <y/list >concatenated.pest

Adding sanity checking is a little bit trickier but still doable. (I'm not doing that part as I don't know if my assumptions even match your use case.)


Since you can supply multiple files to cat it would be nice to only start one instance after some path name mangling:

sed 's|.*|x/&/&.pest|' < y/filename-list.txt | xargs -d '\n' cat

Explanation:

  • sed 's|A|B|' replaces all occurrences of A with B.

    • Here A is .* which matches any character sequence regardless of length or content.

    • & in B is a placeholder for the entire text matched with A.

  • xargs [OPTIONS...] COMMAND [ARGS...] runs COMMAND [ARGS...] after appending the tokens on its standard input stream to the command.

    • Normally tokens are delimited by any amount of white-space character. Using -d tells xargs to use a different delimiter, in this case \n, the newline character.

    • If your xargs installation doesn’t support -d, you need to make sure that the input tokens don’t contain white-space. On Linux, typically you’ll have GNU xargs which does support -d.