bash - tempfile not being given the right name. $BASHPID is changing? -
i thought should straight forward. generate temp file , output it. apparently, there's strangeness happening behind scenes.
function x { cat $2 > /tmp/$bashpid.$$; cat /tmp/$bashpid.$$; # < fails because $bashpid has changed??? }; echo a>/tmp/junk; x $$ /tmp/junk & this works however:
function x { local tmp=/tmp/$bashpid.$$; cat $2 > $tmp; cat $tmp; # < works! }; echo a>/tmp/junk; x $$ /tmp/junk & what $bashpid? thought $$ except if executed in subprocess, subprocesses pid. when executing cat, getting cat's pid?
this particular instance of general issue subshells in bash. don't need $bashpid see it.
the bash manual quite clear redirections , assignments expanded after other words have been expanded:
when simple command executed, shell performs next expansions, assignments, , redirections, left right.
the words parser has marked variable assignments (those preceding command name) , redirections saved later processing. the words not variable assignments or redirections expanded (see shell expansions). if words remain after expansion, first word taken name of command , remaining words arguments. …consequently, next should not surprising:
$ unset tmp; a=$tmp eval "echo ${tmp:=foo} \$a" foo foo here, ${tmp:=foo} expanded before a=$tmp result a=foo passed environment evaluation of echo foo $a.
from here, things murkier. manual says redirections expanded before assignments (actually points 3 , 4; can't markdown co-operate):
redirections performed described above (see redirections). the text after ‘=’ in each variable assignment undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, , quote removal before beingness assigned variable.but see here, assignments seem expanded first:
$ unset tmp; a=$tmp eval <${tmp:=foo} 'echo :$a:' :: $ unset tmp; <${tmp:=foo} a=$tmp eval 'echo :$a:' :: and while manual explicit 1 time bash determines command external utility:
the shell executes named programme in separate execution environment (from next section of manual.)
it's not explicit how much of word expansion in assignments , redirects done in command's execution environment , how much done in original environment. and, indeed, behaviour not predictable.
from experimentation (with bash 4.2), can see that:
assignments expanded in parent environment. redirections expanded in kid environment, if there one. in case of builtins, no kid created, , redirections expanded in parent:$ unset tmp; a=${tmp:=foo} cat </dev/null; echo tmp=$tmp tmp=foo $ unset tmp; >${tmp:=foo} cat </dev/null; echo tmp=$tmp tmp= $ unset tmp; >${tmp:=foo} echo </dev/null; echo tmp=$tmp tmp=foo all of above is, @ least, reasonable, although order of assignments , redirections should, imho, documented more accurately. however, next -- expansion in stdin redirection evaluated twice if file doesn't exist -- bug:
$ tmp=0; /bin/echo .. <$((tmp+=2)); echo $tmp bash: 4: no such file or directory 0 # expected, builtin tmp altered in parent environment $ tmp=0; echo .. <$((tmp+=2)); echo $tmp bash: 4: no such file or directory 4 since $bashpid pid of process in $bashpid expanded, of these various issues impact value. in general, think, safe rule is:
$bashpid anywhere other than: a stand-alone assignment, or a simple parameter expansion in command or argument word. as side note, best way generate name temporary file mktemp utility.
bash
No comments:
Post a Comment