1 | ## oils_failures_allowed: 0
|
2 | ## compare_shells: bash dash mksh zsh
|
3 |
|
4 | # Notes:
|
5 | # - ash is just like dash, so don't bother testing
|
6 | # - zsh fails several cases
|
7 |
|
8 | #### >$file touches a file
|
9 | rm -f myfile
|
10 | test -f myfile
|
11 | echo status=$?
|
12 |
|
13 | >myfile
|
14 | test -f myfile
|
15 | echo status=$?
|
16 |
|
17 | ## STDOUT:
|
18 | status=1
|
19 | status=0
|
20 | ## END
|
21 |
|
22 | ## BUG zsh STDOUT:
|
23 | status=1
|
24 | ## END
|
25 |
|
26 | # regression for OSH
|
27 | ## stderr-json: ""
|
28 |
|
29 | #### $(< $file) yields the contents of the file
|
30 |
|
31 | seq 2 3 > myfile
|
32 | foo=$(< myfile)
|
33 | argv.py "$foo"
|
34 |
|
35 | ## STDOUT:
|
36 | ['2\n3']
|
37 | ## END
|
38 |
|
39 | ## N-I dash/ash/yash STDOUT:
|
40 | ['']
|
41 | ## END
|
42 |
|
43 | #### `< $file` behaves like $(< file)
|
44 |
|
45 | seq 7 8 > myfile
|
46 |
|
47 | x=`< myfile`
|
48 |
|
49 | echo "[$x]"
|
50 |
|
51 | ## STDOUT:
|
52 | [7
|
53 | 8]
|
54 | ## END
|
55 | ## N-I dash/ash/yash STDOUT:
|
56 | []
|
57 | ## END
|
58 |
|
59 | #### $(< file; end) is not a special case
|
60 |
|
61 | seq 5 6 > myfile
|
62 |
|
63 | # zsh prints the file each time!
|
64 | # other shells do nothing?
|
65 |
|
66 | foo=$(echo begin; < myfile)
|
67 | echo $foo
|
68 | echo ---
|
69 |
|
70 | foo=$(< myfile; echo end)
|
71 | echo $foo
|
72 | echo ---
|
73 |
|
74 | foo=$(< myfile; <myfile)
|
75 | echo $foo
|
76 | echo ---
|
77 |
|
78 | ## STDOUT:
|
79 | begin
|
80 | ---
|
81 | end
|
82 | ---
|
83 |
|
84 | ---
|
85 | ## END
|
86 |
|
87 | ## BUG zsh STDOUT:
|
88 | begin
|
89 | 5
|
90 | 6
|
91 | ---
|
92 | 5
|
93 | 6
|
94 | end
|
95 | ---
|
96 | 5
|
97 | 6
|
98 | 5
|
99 | 6
|
100 | ---
|
101 | ## END
|
102 |
|
103 | #### < file in pipeline and subshell doesn't work
|
104 | echo FOO > file2
|
105 |
|
106 | # This only happens in command subs, which is weird
|
107 | < file2 | tr A-Z a-z
|
108 | ( < file2 )
|
109 | echo end
|
110 | ## STDOUT:
|
111 | end
|
112 | ## END
|
113 | ## BUG zsh STDOUT:
|
114 | foo
|
115 | FOO
|
116 | end
|
117 | ## END
|
118 |
|
119 | #### Leading redirect in a simple command
|
120 | echo hello >$TMP/hello.txt # temporary fix
|
121 | <$TMP/hello.txt cat
|
122 | ## stdout: hello
|
123 |
|
124 | #### Redirect in the middle of a simple command
|
125 | f=$TMP/out
|
126 | echo -n 1 2 '3 ' > $f
|
127 | echo -n 4 5 >> $f '6 '
|
128 | echo -n 7 >> $f 8 '9 '
|
129 | echo -n >> $f 1 2 '3 '
|
130 | echo >> $f -n 4 5 '6'
|
131 |
|
132 | cat $f
|
133 | echo
|
134 | ## STDOUT:
|
135 | 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6
|
136 | ## END
|
137 |
|
138 | #### Redirect in command sub
|
139 | FOO=$(echo foo 1>&2)
|
140 | echo $FOO
|
141 | ## stdout:
|
142 | ## stderr: foo
|
143 |
|
144 | #### Redirect in the middle of two assignments
|
145 | FOO=foo >$TMP/out.txt BAR=bar printenv.py FOO BAR
|
146 | tac $TMP/out.txt
|
147 | ## STDOUT:
|
148 | bar
|
149 | foo
|
150 | ## END
|
151 | ## BUG zsh STDOUT:
|
152 | ## END
|
153 |
|
154 | #### Redirect in assignment
|
155 | # dash captures stderr to a file here, which seems correct. Bash doesn't and
|
156 | # just lets it go to actual stderr.
|
157 | # For now we agree with dash/mksh, since it involves fewer special cases in the
|
158 | # code.
|
159 |
|
160 | FOO=$(echo foo 1>&2) 2>$TMP/no-command.txt
|
161 | echo FILE=
|
162 | cat $TMP/no-command.txt
|
163 | echo "FOO=$FOO"
|
164 | ## STDOUT:
|
165 | FILE=
|
166 | foo
|
167 | FOO=
|
168 | ## END
|
169 | ## BUG bash STDOUT:
|
170 | FILE=
|
171 | FOO=
|
172 | ## END
|
173 |
|
174 |
|
175 | #### Redirect in function body
|
176 | fun() { echo hi; } 1>&2
|
177 | fun
|
178 | ## STDOUT:
|
179 | ## END
|
180 | ## STDERR:
|
181 | hi
|
182 | ## END
|
183 |
|
184 | #### Redirect in function body is evaluated multiple times
|
185 | i=0
|
186 | fun() { echo "file $i"; } 1> "$TMP/file$((i++))"
|
187 | fun
|
188 | fun
|
189 | echo i=$i
|
190 | echo __
|
191 | cat $TMP/file0
|
192 | echo __
|
193 | cat $TMP/file1
|
194 | ## STDOUT:
|
195 | i=2
|
196 | __
|
197 | file 1
|
198 | __
|
199 | file 2
|
200 | ## END
|
201 | ## N-I dash stdout-json: ""
|
202 | ## N-I dash status: 2
|
203 |
|
204 | #### Redirect in function body AND function call
|
205 | fun() { echo hi; } 1>&2
|
206 | fun 2>&1
|
207 | ## STDOUT:
|
208 | hi
|
209 | ## END
|
210 | ## STDERR:
|
211 | ## END
|
212 |
|
213 | #### redirect bash extensions: [[ (( for ((
|
214 |
|
215 | case $SH in dash|mksh) exit ;; esac
|
216 |
|
217 | rm -f dbracket dparen for-expr
|
218 |
|
219 | [[ x = x ]] > dbracket
|
220 |
|
221 | (( 42 )) > dparen
|
222 |
|
223 | for ((x = 0; x < 1; ++x)); do
|
224 | echo for-expr
|
225 | done > for-expr
|
226 |
|
227 | wc -l dbracket dparen for-expr
|
228 |
|
229 | ## STDOUT:
|
230 | 0 dbracket
|
231 | 0 dparen
|
232 | 1 for-expr
|
233 | 1 total
|
234 | ## END
|
235 |
|
236 | ## N-I dash/mksh STDOUT:
|
237 | ## END
|
238 |
|
239 | #### redirect if
|
240 | if true; then
|
241 | echo if-body
|
242 | fi >out
|
243 |
|
244 | cat out
|
245 |
|
246 | ## STDOUT:
|
247 | if-body
|
248 | ## END
|
249 |
|
250 | #### redirect case
|
251 | case foo in
|
252 | foo)
|
253 | echo case-body
|
254 | ;;
|
255 | esac > out
|
256 |
|
257 | cat out
|
258 |
|
259 | ## STDOUT:
|
260 | case-body
|
261 | ## END
|
262 |
|
263 | #### redirect while
|
264 | while true; do
|
265 | echo while-body
|
266 | break
|
267 | done > out
|
268 |
|
269 | cat out
|
270 |
|
271 | ## STDOUT:
|
272 | while-body
|
273 | ## END
|
274 |
|
275 | #### redirect for loop
|
276 | for i in $(seq 3)
|
277 | do
|
278 | echo $i
|
279 | done > $TMP/redirect-for-loop.txt
|
280 | cat $TMP/redirect-for-loop.txt
|
281 | ## STDOUT:
|
282 | 1
|
283 | 2
|
284 | 3
|
285 | ## END
|
286 |
|
287 | #### redirect subshell
|
288 | ( echo foo ) 1>&2
|
289 | ## stderr: foo
|
290 | ## stdout-json: ""
|
291 |
|
292 | #### Prefix redirect for loop -- not allowed
|
293 | >$TMP/redirect2.txt for i in $(seq 3)
|
294 | do
|
295 | echo $i
|
296 | done
|
297 | cat $TMP/redirect2.txt
|
298 | ## status: 2
|
299 | ## OK mksh status: 1
|
300 | ## BUG zsh status: 0
|
301 | ## BUG zsh STDOUT:
|
302 | 1
|
303 | 2
|
304 | 3
|
305 | ## END
|
306 |
|
307 | #### Brace group redirect
|
308 | # Suffix works, but prefix does NOT work.
|
309 | # That comes from '| compound_command redirect_list' in the grammar!
|
310 | { echo block-redirect; } > $TMP/br.txt
|
311 | cat $TMP/br.txt | wc -c
|
312 | ## stdout: 15
|
313 |
|
314 | #### Redirect function stdout
|
315 | f() { echo one; echo two; }
|
316 | f > $TMP/redirect-func.txt
|
317 | cat $TMP/redirect-func.txt
|
318 | ## STDOUT:
|
319 | one
|
320 | two
|
321 | ## END
|
322 |
|
323 | #### Nested function stdout redirect
|
324 | # Shows that a stack is necessary.
|
325 | inner() {
|
326 | echo i1
|
327 | echo i2
|
328 | }
|
329 | outer() {
|
330 | echo o1
|
331 | inner > $TMP/inner.txt
|
332 | echo o2
|
333 | }
|
334 | outer > $TMP/outer.txt
|
335 | cat $TMP/inner.txt
|
336 | echo --
|
337 | cat $TMP/outer.txt
|
338 | ## STDOUT:
|
339 | i1
|
340 | i2
|
341 | --
|
342 | o1
|
343 | o2
|
344 | ## END
|