I have a big script which takes a file as input and does various stuff with it. Here is a test version:echo cat: $1cat $1echo grep: $1grep hello $1echo sed: $1sed 's/hello/world/g' $1I want my script to work with process substitution, but only the first command (cat) works, while the rest don't. I think this is because it is a pipe.$ myscript.sh <(echo hello)should print:cat: /dev/fd/63hellogrep: /dev/fd/63hellosed: /dev/fd/63worldIs this possible?
Bash Reuse Process Substitution File
bash;io redirection;process substitution
The <() construct creates a pipe. The pipe is passed via a file name like /dev/fd/63, but this is a special kind of file: opening it really means duplicating file descriptor 63. (See the end of this answer for more explanations.)Reading from a pipe is a destructive operation: once you've caught a byte, you can't throw it back. So your script needs to save the output from the pipe. You can use a temporary file (preferable if the input is large) or a variable (preferable if the input is small). With a temporary file:tmp=$(mktemp)cat <$1 >$tmpcat <$tmpgrep hello <$tmpsed 's/hello/world/g' <$tmprm -f $tmp(You can combine the two calls to cat as tee <$1 -- $tmp.) With a variable:tmp=$(cat)printf %s\nprintf %s\n $tmp | grep helloprintf %s\n $tmp | sed 's/hello/world/g'Note that command substitution $() truncates all newlines at the end of the command's output. To avoid that, add an extra character and strip it afterwards.tmp=$(cat; echo a); tmp=${tmp%a}printf %s\nprintf %s\n $tmp | grep helloprintf %s\n $tmp | sed 's/hello/world/g'By the way, don't forget the double quotes around variable substitutions.