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 |
(exit 4) |
154 |
} |
155 |
echo status=$? |
156 |
echo process_sub=${_process_sub_status[@]} |
157 |
echo pipeline=${_pipeline_status[@]} |
158 |
echo __ |
159 |
} |
160 |
|
161 |
f |
162 |
|
163 |
## STDOUT: |
164 |
1 |
165 |
2 |
166 |
1 |
167 |
2 |
168 |
3 |
169 |
status=4 |
170 |
process_sub=2 3 |
171 |
pipeline=0 4 |
172 |
__ |
173 |
## END |
174 |
## N-I bash STDOUT: |
175 |
1 |
176 |
2 |
177 |
1 |
178 |
2 |
179 |
3 |
180 |
status=4 |
181 |
process_sub= |
182 |
pipeline= |
183 |
__ |
184 |
## END |
185 |
## N-I zsh stdout-json: "" |
186 |
|
187 |
|
188 |
#### process sub in background & |
189 |
|
190 |
cat <(seq 3; sleep 0.1) & wait |
191 |
|
192 |
echo sync |
193 |
|
194 |
# This one escapes, and the shell should still exit |
195 |
cat <(sleep 0.1) & |
196 |
|
197 |
echo fork |
198 |
|
199 |
## STDOUT: |
200 |
1 |
201 |
2 |
202 |
3 |
203 |
sync |
204 |
fork |
205 |
## END |