Re: change in behavior starting with bash-4.3_p14 and $@ in [[...]]
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 8/12/14, 11:05 PM, Mike Frysinger wrote: > simple enough code: > foo=(0 0 0); [[ -z ${foo[@]#0} ]]; echo $? > > with bash-4.3_p13 and older, this would show 0. starting with bash-4.3_p14, > this now shows 1. It's intentional, and part of the same bug fix. Word splitting is suppressed inside [[, so the array expands to a single word ("0 0 0"), the 0s are removed, leaving " ", and that is the result the current version uses. The code before patch 14 ran the string through word splitting, which removed the spaces. FWIW, ksh93 returns the same result as the patched bash, though I can't tell whether it's doing the exact same thing internally. Chet - -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/ -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.11 (Darwin) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlPrbIcACgkQu1hp8GTqdKtKBwCeJrFBvXyzXEzL/HABKzS1ZS/x 32sAn3PEPcEPfUuTRXCHPT+KLWimMJsf =T5NC -END PGP SIGNATURE-
Re: change in behavior starting with bash-4.3_p14 and $@ in [[...]]
On Wed, Aug 13, 2014 at 09:47:51AM -0400, Chet Ramey wrote: > On 8/12/14, 11:05 PM, Mike Frysinger wrote: > > foo=(0 0 0); [[ -z ${foo[@]#0} ]]; echo $? > Word splitting is > suppressed inside [[, so the array expands to a single word ("0 0 0"), the > 0s are removed, leaving " " That doesn't sound right. Either you get a single word and remove the leading 0 only, or you remove the 0s from each array element first, and then get a single word by concatenating what's left. The code that Mike posted is pretty wonky in the first place. I don't understand what its intent is. (It's expanding an array into a list of words in a context where you can't have a list... and then checking the string length of that list-not-list as if it were a string... what?) The right-hand side of an assignment also suppresses word splitting, so I tried this: imadev:~$ foo=(0 0 0); x=${foo[@]#0} imadev:~$ echo "<$x>" <> imadev:~$ foo=(0 0 0); x="${foo[@]#0}" imadev:~$ echo "<$x>" < > imadev:~$ echo $BASH_VERSION 4.3.22(5)-release Looks like the second one expanded to a list of empty words and then concatenated them together with spaces. I have no idea what the first one did, or why it's different.
Cannot trap INT in child of an interactive shell
Bash 4.3.22, HP-UX. imadev:~$ child() { trap - INT; trap 'echo I got an INT; trap - INT; kill -INT $ BASHPID' INT; while true; do sleep 1; done; }; child & [1] 19116 imadev:~$ kill -INT 19116 imadev:~$ kill -INT 19116 imadev:~$ kill -TERM 19116 [1]+ Terminated child The manual says: Non-builtin commands run by bash have signal handlers set to the values inherited by the shell from its parent. When job control is not in effect, asynchronous commands ignore SIGINT and SIGQUIT in addition to these inherited handlers. And yes, turning on job control magically makes it work: imadev:~$ child() { set -m; trap - INT; trap 'echo I got an INT; trap - INT; kil l -INT $BASHPID' INT; while true; do sleep 1; done; }; child & [1] 19127 imadev:~$ kill -INT 19127 imadev:~$ I got an INT [1]+ Interrupt child But I don't understand why job control is needed to override an inherited (or automatically created) trap. Shouldn't an explicit trap always be used? Ksh (88) does not have this problem: imadev:~$ ksh $ child() { trap - INT; trap 'echo I got an INT; trap - INT; kill -INT $BASHPID' INT; while true; do sleep 1; done; }; child & [1] 19133 $ kill -INT 19133 $ I got an INT child: kill: bad argument count (Of course, ksh also doesn't have BASHPID, so ignore that last bit.)
Re: Feature request - ganged file test switches
On Aug 12, 2014, at 4:36 PM, Chet Ramey wrote: > On 8/9/14, 7:07 AM, Steve Simmons wrote: > >> It would be nice to have ganged file test switches. As an example, to test >> that a directory exists and is properly accessible one could do >> >> if [[ -d foo ]] && [[ -r foo ]] && [[ -x foo ]] ; then . . . >> >> but >> >> if [[ -drx foo ]] ; then . . . >> >> is a lot easier. > > Sure, but it's only syntactic sugar. Knew that going in :-). Other discussion points out how limited it is; I'm perfectly happy pulling back. My thoughts on how to do this more flexibly boil down to the capabilities gnu find has w/r/t file types and modes. Unfortunately we have a few systems which lack gnu find and are "vendor supported appliances" (eyeroll) and we're unable to add new software beyond simple scripts. Which also means that any new bash feature would probably be unavailable for years, so it's not like this is a big loss. If others have no interest in this syntactic sugar I see little point to adding it; a broader and more flexible solution is just to use find as above.
Script with set -m launched from interactive shell makes all ancestor shells die
This was tested on bash 4.3.22 (HP-UX) and bash 4.2.37 (Linux). Create a script named foo with the following content: #!/bin/bash set -m while sleep 1; do :; done Make it executable, and type ./foo & at an interactive shell. You get your shell prompt back. You can press Enter as many times as you like. But if you press any key other than Enter, the entire terminal window goes away. Wrapping a few shells around it only postpones the inevitable. If you run a few nested "bash" shells as padding, and then run ./foo & in the innermost one, each non-Enter keystroke will kill one instance of bash, printing the word "exit" on the terminal. When all the shells die, so does the terminal. wooledg@wooledg:~$ bash wooledg@wooledg:~$ bash wooledg@wooledg:~$ bash wooledg@wooledg:~$ bash wooledg@wooledg:~$ ./foo & [1] 11945 wooledg@wooledg:~$ aexit wooledg@wooledg:~$ bexit wooledg@wooledg:~$ cexit wooledg@wooledg:~$ dexit wooledg@wooledg:~$ (The next keystroke after that removes the terminal.)
Re: Feature request - ganged file test switches
On Wed, Aug 13, 2014 at 12:16:52PM -0400, Steve Simmons wrote: > > On Aug 12, 2014, at 4:36 PM, Chet Ramey wrote: > > > On 8/9/14, 7:07 AM, Steve Simmons wrote: > > > >> It would be nice to have ganged file test switches. As an example, to test > >> that a directory exists and is properly accessible one could do > >> > >> if [[ -d foo ]] && [[ -r foo ]] && [[ -x foo ]] ; then . . . > >> > >> but > >> > >> if [[ -drx foo ]] ; then . . . > >> > >> is a lot easier. > > > > Sure, but it's only syntactic sugar. > > Knew that going in :-). Other discussion points out how limited it is; > I'm perfectly happy pulling back. My thoughts on how to do this more > flexibly boil down to the capabilities gnu find has w/r/t file types > and modes. Unfortunately we have a few systems which lack gnu find > and are "vendor supported appliances" (eyeroll) and we're unable to > add new software beyond simple scripts. Which also means that any new > bash feature would probably be unavailable for years, so it's not like > this is a big loss. > > If others have no interest in this syntactic sugar I see little point > to adding it; a broader and more flexible solution is just to use find > as above. I like the idea, but switch negation would need to be supported, and I don't think that's been covered sufficiently. Using ! as a switch modifier might be possible, and I like it, but would then also apply to single filetest switches, e.g., -!e foo would be the same as ! -e foo. Maybe that's possible, but it seems a fairly major addition to the syntax. Using caps for switch negation is pretty common, but the filetest switches already use some uppercase values, so I don't think that's possible in this case. I'm a little confused about the 'before' example: if [[ -d foo ]] && [[ -r foo ]] && [[ -x foo ]] ; then . . . I thought that && could be used reliably within the [[ ]] construct, including short-circuiting the tests, so this could be: if [[ -d foo && -r foo && -x foo ]] ; then . . . I don't see how the bundled switces could be ambiguous, so must be missing something. Ken
Re: change in behavior starting with bash-4.3_p14 and $@ in [[...]]
On 8/13/14, 10:09 AM, Greg Wooledge wrote: > On Wed, Aug 13, 2014 at 09:47:51AM -0400, Chet Ramey wrote: >> On 8/12/14, 11:05 PM, Mike Frysinger wrote: >>> foo=(0 0 0); [[ -z ${foo[@]#0} ]]; echo $? > >> Word splitting is >> suppressed inside [[, so the array expands to a single word ("0 0 0"), the >> 0s are removed, leaving " " > > That doesn't sound right. Either you get a single word and remove the > leading 0 only, or you remove the 0s from each array element first, > and then get a single word by concatenating what's left. Not quite. The expansion happens before word splitting, and the @ causes the result to be treated specially. This is the basic set of steps: 1. The foo[@] is expanded into a list (0 0 0), noting that the @ was present so the result can be handled accordingly. 2. The #0 is applied to each member of the list, as it would be in any other context. If you were to echo the results here, kind of like you did below, you would get three empty words. 3. The results are `glued' together as if $* were used, due to the presence of `@', so the three empty words are separated by two spaces. 4. The two spaces remain because word splitting is not performed; the empty words disappear. > The code that Mike posted is pretty wonky in the first place. I don't > understand what its intent is. (It's expanding an array into a list of > words in a context where you can't have a list... and then checking the > string length of that list-not-list as if it were a string... what?) Yeah, I assume it's a quick way to test whether all elements of an array are identical. > > The right-hand side of an assignment also suppresses word splitting, so > I tried this: > > imadev:~$ foo=(0 0 0); x=${foo[@]#0} > imadev:~$ echo "<$x>" > <> > imadev:~$ foo=(0 0 0); x="${foo[@]#0}" > imadev:~$ echo "<$x>" > < > > imadev:~$ echo $BASH_VERSION > 4.3.22(5)-release > > Looks like the second one expanded to a list of empty words and then > concatenated them together with spaces. I have no idea what the first > one did, or why it's different. It looks like a bug. I assume it's because bash treats "$@" and $@ (and their array equivalents) differently, even in contexts where word splitting is not going to happen. I will have to look at it. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: Cannot trap INT in child of an interactive shell
On 8/13/14, 12:08 PM, Greg Wooledge wrote: > Bash 4.3.22, HP-UX. > > imadev:~$ child() { trap - INT; trap 'echo I got an INT; trap - INT; kill > -INT $ > BASHPID' INT; while true; do sleep 1; done; }; child & > [1] 19116 > imadev:~$ kill -INT 19116 > imadev:~$ kill -INT 19116 > imadev:~$ kill -TERM 19116 > [1]+ Terminated child > > The manual says: > > Non-builtin commands run by bash have signal handlers set to the > values inherited by the shell from its parent. When job control is > not in effect, asynchronous commands ignore SIGINT and SIGQUIT in > addition to these inherited handlers. > > And yes, turning on job control magically makes it work: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_11: "When a command is in an asynchronous list, it shall inherit from the shell a signal action of ignored (SIG_IGN) for the SIGQUIT and SIGINT signals, and may inherit a signal mask in which SIGQUIT and SIGINT are blocked. Otherwise, the signal actions and signal mask inherited by the command shall be the same as those inherited by the shell from its parent unless a signal action is modified by the trap special built-in (see trap)." The idea is to protect asynchronous children from keyboard-generated signals, since all child processes belong to the same process group as the shell, and keyboard signals are sent to all processes in the terminal's process group. When job control is active, all child jobs are in separate process groups, so this is not an issue and doesn't need to happen. That, combined with this: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_28 "Signals that were ignored on entry to a non-interactive shell cannot be trapped or reset, although no error need be reported when attempting to do so." means that bash doesn't allow signals that were ignored when it started, whether that is a separate invocation or a forked child running a command, to be changed via `trap'. There has been some discussion on the Posix list about exactly what "on entry" means, but nothing conclusive. (And, FWIW, ksh93 behaves as bash does in this regard.) Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: Script with set -m launched from interactive shell makes all ancestor shells die
On 8/13/14, 12:42 PM, Greg Wooledge wrote: > This was tested on bash 4.3.22 (HP-UX) and bash 4.2.37 (Linux). > > Create a script named foo with the following content: > > #!/bin/bash > set -m > while sleep 1; do :; done > > Make it executable, and type > > ./foo & > > at an interactive shell. You get your shell prompt back. You can press > Enter as many times as you like. But if you press any key other than > Enter, the entire terminal window goes away. I haven't looked at this yet, but here's what I bet is happening: turning on job control with set -m causes several things to happen: the shell creates a new process group and becomes the process group leader, sets the terminal's process group to its own process group, and creates children in their own process group. Now that the terminal is no longer in the parent shell's process group, reads return EOF (or -1/EIO), and the parent shell exits. The details may not be exactly this, but this is the general set of events. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: Feature request - ganged file test switches
On Aug 13, 2014, at 2:31 PM, Ken Irving wrote: > I like the idea, but switch negation would need to be supported, and > I don't think that's been covered sufficiently. Using ! as a switch > modifier might be possible, and I like it, but would then also apply to > single filetest switches, e.g., -!e foo would be the same as ! -e foo. > Maybe that's possible, but it seems a fairly major addition to the syntax. Agree on all. > I'm a little confused about the 'before' example: > >if [[ -d foo ]] && [[ -r foo ]] && [[ -x foo ]] ; then . . . > > I thought that && could be used reliably within the [[ ]] construct, > including short-circuiting the tests, so this could be: > >if [[ -d foo && -r foo && -x foo ]] ; then . . . > > I don't see how the bundled switces could be ambiguous, so must be > missing something. Both forms work, which I didn't expect. Learn something new every day; thanks.