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
|