Re: using exec to close a fd in a var crashes bash
On Wed, 23 Aug 2023, 12:20 Greg Wooledge, wrote: > > echo Hi {X}>/dev/null > > ls -l "/proc/$$/fd/$X" > > That's a really strange example. I wonder what would lead someone to > write that particular redirection. Oh I merely wanted to point out that the redirection persists beyond the echo command. It's basically the same as your example: The thing I was testing was in response to this question, which was posed > as an exercise: > > Swap stderr and stdout of a shell command. > > I gave […] > > cmd {fd}>&1 1>&2 2>&$fd {fd}>&- > > [which] does *not* close the temporary file > descriptor Well, it closes at as far as cmd is concerned, but not as far as the Shell is concerned. I would expect {fd}>&- to exactly undo {fd}>/path (or {fd}>&$otherfd), so they should either both be local to the command, or both apply to the shell. Indeed quite I'm perplexed as to why it wasn't designed this way to begin with. I'm also mystified as to why they persist, in stark contrast to other redirections, but that's comparatively less important. (I recall there was some discussion about the variable persisting, but I didn't think it implied the fd itself would persist.) This seems like a clear example of an experimental feature that should have been indicated as such in the release notes, and only enabled when explicitly chosen at build time (e.g. ./configure --enable-all-experimental-features-without-warnings). Chopping and changing behaviour in "permanent" releases creates a maintenance nightmare. -Martin
Re: using exec to close a fd in a var crashes bash
On Wed, Aug 23, 2023 at 12:05:42PM +1000, Martin D Kealey wrote: > On Wed, 23 Aug 2023, 05:29 Greg Wooledge, wrote: > > > Excuse me now, while I go and close several open FDs in the shell where > > I tested something the other day, which I had no idea were left open. > > > > It's even worse than that; try: > > echo Hi {X}>/dev/null > ls -l "/proc/$$/fd/$X" That's a really strange example. I wonder what would lead someone to write that particular redirection. What's the intended outcome, in terms of the variable X and the state of file descriptors? If you simply want to discard output, there's no reason I can think of to use {X}>/dev/null instead of simply >/dev/null. The thing I was testing was in response to this question, which was posed as an exercise: Swap stderr and stdout of a shell command. I gave two answers: cmd 3>&1 1>&2 2>&3 3>&- and cmd {fd}>&1 1>&2 2>&$fd {fd}>&- As it turns out, the second one does *not* close the temporary file descriptor, so each time I ran the function while testing, an extra file descriptor was left open. But this variant *does* close it: cmd {fd}>&1 1>&2 2>&$fd exec {fd}>&- I find this incredibly confusing.
Re: using exec to close a fd in a var crashes bash
On Wed, 23 Aug 2023, 05:29 Greg Wooledge, wrote: > Excuse me now, while I go and close several open FDs in the shell where > I tested something the other day, which I had no idea were left open. > It's even worse than that; try: echo Hi {X}>/dev/null ls -l "/proc/$$/fd/$X" -Martin >
Re: using exec to close a fd in a var crashes bash
On Tue, Aug 22, 2023 at 02:59:14PM -0400, Dale R. Worley wrote: > The "{var}>..." mechanism *assigns* to $var, rather than > taking its existing value. ... oh. Well, today I learned something. Excuse me now, while I go and close several open FDs in the shell where I tested something the other day, which I had no idea were left open.
Re: using exec to close a fd in a var crashes bash
On 8/22/23 2:59 PM, Dale R. Worley wrote: Is there any way to write a redirection "Redirect the fd whose number is in $FOO to file /foo/bar?" OK, you can write 'bash -c "..."' and assemble a command string however you want. But is there a direct way to write it? The "{var}>..." mechanism *assigns* to $var, rather than taking its existing value. If you want an extra round of word expansion, use eval. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: using exec to close a fd in a var crashes bash
Is there any way to write a redirection "Redirect the fd whose number is in $FOO to file /foo/bar?" OK, you can write 'bash -c "..."' and assemble a command string however you want. But is there a direct way to write it? The "{var}>..." mechanism *assigns* to $var, rather than taking its existing value. Dale
Re: read -E with read -d in completion function
On 8/21/23 5:50 PM, Grisha Levit wrote: The new read -E option is a nice addition. I think it's not unreasonable for a completion function to itself invoke `read' (with a file or pipe as input, not a tty) and this mostly works out fine, unless the -d option is used since the builtin stores the delimiter arg in a static variable: Thanks for the suggestion. This looks reasonable. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Error handling with nofork command substitution
Hi, With the new funsub syntax ${ cmd;} and ${| cmd;} that encourages returning the value of $REPLY to the caller, I've been thinking about an idiomatic way of doing error handling and propagation that may call for a new shell option or new type of funsub. So the idea is natural, when a function encounters an error condition it "raises" an error message by setting it in $REPLY and returning a non-zero exit code, when there's no error it simply sets $REPLY to a return value and returns a zero exit code. For example: function div { local -i x="$1" y="$2" if ((y==0)); then REPLY='CANNOT DIVIDE BY 0' return 100 else REPLY=$((x/y)) fi } function bin { local -i x="$1" case "$x" in (*[!01]*) REPLY='NOT BINARY NUMBER: '"$x" return 200 ;; (*) REPLY=$((2#$x)) esac } Now, "catching" an error can be done with an if or case statement plus ${| cmd;} and propagation can be done by simply returning the exit code (which the caller has to again catch with REPLY=${| cmd;}). For example: function main { REPLY=${| bin 10102; } case $? in (0) ;; (*) local code=$? echo "Error Message: [$REPLY], Exit Code: [$code]" return $code esac echo "There was no error! Decimal: $REPLY" } This is good but verbose for propagation, to address this languages like Rust or Swift introduced a `?` operator that simply returns back the code and message to the caller. We could emulate this in Bash like this: function ? { if REPLY=${| "$@"; }; then printf -- '%s' "$REPLY" else return $? fi } function calculation_steps { local -i ratio bi ratio=${ ? div 10 5 ;} || return $? # ratio = div(10,5)?; bi=${ ? bin "$ratio" ;} || return $? # bi = bin(ratio)?; REPLY="$bi" } If there was an error in a step, it gets propagated, if not, we return the REPLY value. And here is where I'd like to have like an option or syntactic sugar that allows me to nest funsubs but returning out of the funsub if an error was found, simulating `?` method chaining like in those other languages. This one doesn't work: bi=${ ? bin ${ ? div 10 5; } ; } || return $? # bi = div(10,5)?.bin()?; This one does work, but is not better than the original: bi=${ ratio=${ ? div 10 5; } || return $? ? bin "$ratio" } || return $? Something like: bi=${? bin ${? div 10 5; } ; } # (1) bi=${ div 10 5 ?| bin ; }# (2) bi=${ local - set -o errpropagate# (3) ? bin ${ ? div 10 5; } } I haven't found a solution in pure bash so that's why I'm throwing new syntax ideas and making this thread; maybe there is and I'd love to know, otherwise one of these 3 constructions could be implemented if users find it useful. (1) is clean, but parsing could be tricky because of $? (2) would resemble method chaining in other languages but it's not very idiomatic and probably the hardest to implement (3) is probably easier to implement, no new syntax, but users would still have to know and define their `?` propagation function I'd also like some feedback on this error handling strategy. Is there a better way? Does it have pitfalls? Thanks, José