1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
# Tests for process substitution: <(...), >(...) and =(...).
%prep
if grep '#define PATH_DEV_FD' $ZTST_testdir/../config.h > /dev/null 2>&1 ||
grep '#define HAVE_FIFOS' $ZTST_testdir/../config.h > /dev/null 2>&1; then
mkdir procsubst.tmp
cd procsubst.tmp
print 'First\tSecond\tThird\tFourth' >FILE1
print 'Erste\tZweite\tDritte\tVierte' >FILE2
else
ZTST_unimplemented="process substitution is not supported"
true
fi
function copycat { cat "$@" }
%test
paste <(cut -f1 FILE1) <(cut -f3 FILE2)
0:<(...) substitution
>First Dritte
# slightly desperate hack to force >(...) to be synchronous
{ paste <(cut -f2 FILE1) <(cut -f4 FILE2) } > >(sed 's/e/E/g' >OUTFILE)
cat OUTFILE
0:>(...) substitution
>SEcond ViErtE
diff =(cat FILE1) =(cat FILE2)
1:=(...) substitution
>1c1
>< First Second Third Fourth
>---
>> Erste Zweite Dritte Vierte
copycat <(print First) <(print Zweite)
0:FDs remain open for external commands called from functions
>First
>Zweite
catfield2() {
local -a args
args=(${(s.,.)1})
print $args[1]
cat $args[2]
print $args[3]
}
catfield2 up,<(print $'\x64'own),sideways
0:<(...) when embedded within an argument
>up
>down
>sideways
outputfield2() {
local -a args
args=(${(s.,.)1})
print $args[1]
echo 'How sweet the moonlight sits upon the bank' >$args[2]
print $args[3]
}
outputfield2 muddy,>(sed -e s/s/th/g >outputfield2.txt),vesture
# yuk
while [[ ! -e outputfield2.txt || ! -s outputfield2.txt ]]; do :; done
cat outputfield2.txt
0:>(...) when embedded within an argument
>muddy
>vesture
>How thweet the moonlight thitth upon the bank
catfield1() {
local -a args
args=(${(s.,.)1})
cat $args[1]
print $args[2]
}
catfield1 =(echo s$'\x69't),jessica
0:=(...) followed by something else without a break
>sit
>jessica
(
setopt nonomatch
# er... why is this treated as a glob?
print everything,=(here is left),alone
)
0:=(...) preceded by other stuff has no special effect
>everything,=(here is left),alone
print something=${:-=(echo 'C,D),(F,G)'}
1: Graceful handling of bad substitution in enclosed context
?(eval):1: unterminated `=(...)'
# '`
() {
print -n "first: "
cat $1
print -n "second: "
cat $2
} =(echo This becomes argument one) =(echo and this argument two)
function {
print -n "third: "
cat $1
print -n "fourth: "
cat $2
} =(echo This becomes argument three) =(echo and this argument four)
0:Process environment of anonymous functions
>first: This becomes argument one
>second: and this argument two
>third: This becomes argument three
>fourth: and this argument four
() {
# Make sure we don't close the file descriptor too early
eval 'print "Execute a complicated command first" | sed s/command/order/'
cat $1
} <(echo This line was brought to you by the letters F and D)
0:Process substitution as anonymous function argument
>Execute a complicated order first
>This line was brought to you by the letters F and D
alias foo='cat <('
eval 'foo echo this is bound to work)'
0:backtacking within command string parsing with alias still pending
>this is bound to work
alias foo='cat <( print'
eval 'foo here is some output)'
0:full alias expanded when substitution starts in alias
>here is some output
if ! (mkfifo test_pipe >/dev/null 2>&1); then
ZTST_skip="mkfifo not available"
else
echo 1 | tee >(cat > test_pipe) | (){
local pipein
read pipein <test_pipe
print $pipein
read pipein
print $pipein
}
fi
0:proc subst fd in forked subshell closed in parent
>1
>1
if [[ ! -e test_pipe ]]; then
ZTST_skip="mkfifo not available"
else
echo 1 | tee >(cat > test_pipe) | paste - test_pipe
fi
0:proc subst fd in forked subshell closed in parent (external command)
>1 1
procfunc() {
cat <(cat "$@")
}
procfunc <(echo argument)
0:With /proc/self file descriptors must not be tidied up too early
>argument
|