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
|