Bash Scripting – Disable Undesirable Shell Prompt in Process Substitution

bashscriptingshell-script

NOTE: This question has arisen due to asynchronous processing of 'Process Substitution'. The script responses were deceptive, causing many lost hours. A previously related post is here: cat in process substitution hangs: what is it waiting for?

Bash 4.4.19(1)-release

Using this code because I cannot use pipes.

func() { 
    in=$(cat)
    echo "'this is it: $in'"    
}

echo "a string" > >(func)

This Process Substitution unfortunately is printing the prompt along with my string.

user@srv:~$ ./test.sh
user@srv:~$ 'this is it: a string'

This is undesirable for my usage! to say the least!!!

What is desirable is normal behavior like so:

user@srv:~$ ./test.sh
'this is it: a string'

Can I force Process Substitution not to print a shell prompt?

NOTE: I cannot use pipes… it creates other problems for me.
These are the problems it creates:
Can I process command output just before sending it to a file (one liner)?

Best Answer

That happens because your script returns before the subprocess from the >(...) process substitution, which runs asynchronously (ie in the background) and will only come to print its stuff after the shell you called your script from already printed its prompt.

The solution is to wait for it; unfortunately, processes run in subshells, etc. are not managed as part of jobs and do not appear in bash's job table, so you'll have to made do with pgrep -P (find-by-parent):

func() {
    in=$(cat)
    sleep .2
    echo "'this is it: $in'"
}

echo "a string" > >(func)
wait $(pgrep -P $$)

(I've added the sleep .2 just to prevent the symptom from spuriously disappearing -- the extra time the pgrep and wait take to run may be enough for the asynchronous process to terminate, too).

The assumption that processes running inside > >(...) are children of the main script only holds true when they're used with builtins, functions and group commands, see here for more details.

Related Question