0

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)?

  • Your code does not capture your prompt, it captures input. Your prompt is already stored in an environment variable named PS1 though. – Jesse_b Jun 12 at 21:51
  • when I run echo "'${PS1}'" in the shell, I get '\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' – conanDrum Jun 12 at 21:56
  • when I run echo "'${PS1}'" in the script, i get '' – conanDrum Jun 12 at 21:57
  • I noticed that. however I would still like to accomplish this undertaking. – conanDrum Jun 12 at 22:55
  • 1
    Could you say a bit more how the actual value of the prompt ends up in your variable? The prompt is written to the shell's standard error output stream. You would have to actually hop through some hoops to capture it... – Kusalananda Jun 12 at 23:04
1

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.

  • Thanks, please give me a moment to check this... Also, Kusalananda mentioned this: "...The prompt is written to the shell's standard error output stream.... – Kusalananda♦ 1 hour ago" Is it an idea maybe to disable the STDERR so that the prompt does not display before the ECHO and then enable it again? – conanDrum Jun 13 at 0:30
  • Don't hurry ;-) It's not a good idea to disable the stderr because you may miss error messages written to it. – mosvy Jun 13 at 0:35
  • and of course it is related to my previous question 3 hours ago, but people are too quick to provide unhelpful answers. Thanks for making this clear to me mosvy. here: unix.stackexchange.com/questions/524534/… – conanDrum Jun 13 at 0:39
  • Thank you mosvy for pointing in the right direction. – conanDrum Jun 13 at 0:55
  • is it really necessary to sleep .2? it seems enough to just wait $(pgrep -P $$) – conanDrum Jun 13 at 0:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.