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 cat <(seq 2; exit 2) <(seq 3; exit 3)
79 echo status=${_process_sub_status[@]}
80 echo done
81
82 ## STDOUT:
83 1
84 2
85 1
86 2
87 3
88 status=2 3
89 done
90 ## END
91 ## N-I bash/zsh STDOUT:
92 1
93 2
94 1
95 2
96 3
97 status=
98 done
99 ## END
100
101 #### shopt -s process_sub_fail
102
103 cat <(echo a; exit 2) <(echo b; exit 3)
104 echo status=$? ps=${_process_sub_status[@]}
105
106 echo __
107 shopt -s process_sub_fail
108
109 cat <(echo a; exit 2) <(echo b; exit 3)
110 echo status=$? ps=${_process_sub_status[@]}
111
112 # Now exit because of it
113 set -o errexit
114
115 cat <(echo a; exit 2) <(echo b; exit 3)
116 echo status=$? ps=${_process_sub_status[@]}
117
118 ## status: 3
119 ## STDOUT:
120 a
121 b
122 status=0 ps=2 3
123 __
124 a
125 b
126 status=3 ps=2 3
127 a
128 b
129 ## END
130 ## N-I bash/zsh status: 0
131 ## N-I bash/zsh STDOUT:
132 a
133 b
134 status=0 ps=
135 __
136 a
137 b
138 status=0 ps=
139 a
140 b
141 status=0 ps=
142 ## END
143
144 #### process subs and pipelines together
145
146 # zsh is very similar to bash, but don't bother with the assertions
147 case $SH in (zsh) exit ;; esac
148
149
150 f() {
151 cat <(seq 1; exit 1) | {
152 cat <(seq 2; exit 2) <(seq 3; exit 3)
153
154 # 2022-11 workaround for race condition: sometimes we get pipeline=141 4
155 # instead of pipeline=0 4, which means that the first 'cat' got SIGPIPE.
156 # If we make this part of the pipeline take longer, then 'cat' should have
157 # a chance to finish.
158
159 sleep 0.01
160
161 (exit 4)
162 }
163 echo status=$?
164 echo process_sub=${_process_sub_status[@]}
165 echo pipeline=${_pipeline_status[@]}
166 echo __
167 }
168
169 f
170
171 ## STDOUT:
172 1
173 2
174 1
175 2
176 3
177 status=4
178 process_sub=2 3
179 pipeline=0 4
180 __
181 ## END
182 ## N-I bash STDOUT:
183 1
184 2
185 1
186 2
187 3
188 status=4
189 process_sub=
190 pipeline=
191 __
192 ## END
193 ## N-I zsh stdout-json: ""
194
195
196 #### process sub in background &
197
198 cat <(seq 3; sleep 0.1) & wait
199
200 echo sync
201
202 # This one escapes, and the shell should still exit
203 cat <(sleep 0.1) &
204
205 echo fork
206
207 ## STDOUT:
208 1
209 2
210 3
211 sync
212 fork
213 ## END