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