1
2 #### Process sub input
3 f=_tmp/process-sub.txt
4 { echo 1; echo 2; echo 3; } > $f
5 cat <(head -n 2 $f) <(tail -n 2 $f)
6 ## STDOUT:
7 1
8 2
9 2
10 3
11 ## END
12
13 #### Process sub from external process to stdin
14 seq 3 > >(tac)
15 ## STDOUT:
16 3
17 2
18 1
19 ## END
20
21 #### Process sub from shell to stdin
22 { echo 1; echo 2; echo 3; } > >(tac)
23 ## STDOUT:
24 3
25 2
26 1
27 ## END
28
29 #### Non-linear pipeline with >()
30 stdout_stderr() {
31 echo o1
32 echo o2
33
34 sleep 0.1 # Does not change order
35
36 { echo e1;
37 echo warning: e2
38 echo e3;
39 } >& 2
40 }
41 stdout_stderr 2> >(grep warning) | tac >$TMP/out.txt
42 wait $! # this does nothing in bash 4.3, but probably does in bash 4.4.
43 echo OUT
44 cat $TMP/out.txt
45 # PROBLEM -- OUT comes first, and then 'warning: e2', and then 'o2 o1'. It
46 # looks like it's because nobody waits for the proc sub.
47 # http://lists.gnu.org/archive/html/help-bash/2017-06/msg00018.html
48 ## STDOUT:
49 OUT
50 warning: e2
51 o2
52 o1
53 ## END
54
55 #### $(<file) idiom with process sub
56 echo FOO >foo
57
58 # works in bash and zsh
59 echo $(<foo)
60
61 # this works in zsh, but not in bash
62 tr A-Z a-z < <(<foo)
63
64 cat < <(<foo; echo hi)
65
66 ## STDOUT:
67 FOO
68 hi
69 ## END
70 ## OK zsh STDOUT:
71 FOO
72 foo
73 FOO
74 hi
75 ## END
76
77 #### status code is available
78
79 shopt --set parse_at
80
81 cat <(seq 2; exit 2) <(seq 3; exit 3)
82
83 case $SH in bash|zsh) exit ;; esac
84
85 echo status @_process_sub_status
86 echo done
87
88 ## STDOUT:
89 1
90 2
91 1
92 2
93 3
94 status 2 3
95 done
96 ## END
97 ## N-I bash/zsh STDOUT:
98 1
99 2
100 1
101 2
102 3
103 ## END
104
105 #### shopt -s process_sub_fail
106
107 case $SH in bash|zsh) exit ;; esac
108
109 shopt --set parse_at
110
111 cat <(echo a; exit 2) <(echo b; exit 3)
112 echo status=$? ps @_process_sub_status
113
114 echo __
115 shopt -s process_sub_fail
116
117 cat <(echo a; exit 2) <(echo b; exit 3)
118 echo status=$? ps @_process_sub_status
119
120 # Now exit because of it
121 set -o errexit
122
123 cat <(echo a; exit 2) <(echo b; exit 3)
124 echo status=$? ps @_process_sub_status
125
126 ## status: 3
127 ## STDOUT:
128 a
129 b
130 status=0 ps 2 3
131 __
132 a
133 b
134 status=3 ps 2 3
135 a
136 b
137 ## END
138 ## N-I bash/zsh status: 0
139 ## N-I bash/zsh STDOUT:
140 ## END
141
142 #### process subs and pipelines together
143
144 # zsh is very similar to bash, but don't bother with the assertions
145 case $SH in bash|zsh) exit ;; esac
146
147 shopt --set parse_at
148
149 f() {
150 cat <(seq 1; exit 1) | {
151 cat <(seq 2; exit 2) <(seq 3; exit 3)
152
153 # 2022-11 workaround for race condition: sometimes we get pipeline=141 4
154 # instead of pipeline=0 4, which means that the first 'cat' got SIGPIPE.
155 # If we make this part of the pipeline take longer, then 'cat' should have
156 # a chance to finish.
157
158 sleep 0.01
159
160 (exit 4)
161 }
162 echo status=$?
163 echo process_sub @_process_sub_status
164 echo pipeline @_pipeline_status
165 echo __
166 }
167
168 f
169
170 ## STDOUT:
171 1
172 2
173 1
174 2
175 3
176 status=4
177 process_sub 2 3
178 pipeline 0 4
179 __
180 ## END
181 ## N-I bash/zsh STDOUT:
182 ## END
183
184 #### process sub in background &
185
186 cat <(seq 3; sleep 0.1) & wait
187
188 echo sync
189
190 # This one escapes, and the shell should still exit
191 cat <(sleep 0.1) &
192
193 echo fork
194
195 ## STDOUT:
196 1
197 2
198 3
199 sync
200 fork
201 ## END