Re: equivalent of Linux readlink -f in pure bash?
On Wed, Aug 10, 2011 at 6:00 PM, Bernd Eggink mono...@sudrala.de wrote: On 09.08.2011 15:50, Steven W. Orr wrote: *) You reset OPTIND to 1 but you didn't declare it local. This will cause any caller of getlink which uses getopts to reset its variable to 1. (I mention this because it cost me a couple of hours a while back.) The reason I didn't declare OPTIND local is that OPTIND is handled specially by the shell; there is always exactly _one_ instance of this variable. In other words, OPTIND is always global, even if declared local (which is indeed pretty weird). Try this: I always declare OPTIND as local. I didn't know it does not work at all. Bug? --**- function f { local OPTIND=1 echo \$1=$1 } while getopts abcdefg opt do echo opt=$opt f $opt done --**-- Calling the sript like this works fine: script -a -b -c But calling it like this leads to an endless loop: script -abc One could of course save and restore the original: --**- function f { local oldind=$OPTIND OPTIND=1 echo \$1=$1 OPTIND=$oldind } --**- However, this also loops endlessly. The reason is most likely that bash maintains an additional internal variable holding the index of the current character, relative to the current word. While this variable is not directly accessible by the user, it is set to 0 whenever OPTIND is assigned a value. So the only safe way is to _never_ use getopts within another getopts block, but always wait until the first one has finished.
Aw: Re: Inline `ifdef style` debugging
Hello, Am Montag, 8. August 2011 19:20:25 UTC+2 schrieb Steven W. Orr: if (( debug )) then _debug() { $@ # I do question whether this is a viable construct, versus # eval $@ } else _debug() { : } fi on bash-hackers.org I found this, which I think is the ultimate method to write a debug-function: _debug() { if $whatever_test_you_prefer; then _debug() { $@ } else _debug() { : } fi _debug $@ } they call it collapsing functions: http://wiki.bash-hackers.org/howto/collapsing_functions have fun, Peter
Re: usenet to email gateway
2011-08-10 23:05:26 +, Karl Berry: not sure who to report that to I've asked the FSF sysadmins. I can see from the mailing list configuration that the gateway is intended to be operational, but don't know how to debug what it happening from there. [...] Thanks Karl. My last successful post to gnu.bash.bug was on 2011-04-12 15:30:20 GMT http://thread.gmane.org/gmane.comp.shells.bash.bugs/16603 and Chet's answer suggests it made its way to the mailing list only months later. I'll repost my messages to the mailing list and try and cancel them on usenet. In the meantime, it might be worth pointing out that posting to the gnu.bash.bug newsgroup doesn't work (well it works, but only usenet users see the messages, not those subscribed to the mailing list only). -- Stephane
Mailcheck during completion
Hi! I often get a bash message about new mail during command line completion. Steps to reproduce: Type ls ~/.bas and press tab. Expected result: Command line completed to ls ~/.bash or whatever is right. Actual result: If new mails have arrived, the mail check is performed when pressing tab, rendering the whole command line like this: $ ls ~/.basYou have mail in /var/mail/user h This is a real problem for both readability and subsequent editing of the command line. I would therefore like to see bash modified in such a way that the mail check is never executed in response to a completion. Instead, the only places where such a check should be performed are in my opinion the initial prompt after startup and any prompt after a command was actually executed. Just pressing enter with an empty command line should also do the check, I think. Greetings, Martin von Gagern signature.asc Description: OpenPGP digital signature
Re: Re: Inline `ifdef style` debugging
On Thu, Aug 11, 2011 at 12:23:00AM -0700, pjodrr wrote: Hello, Am Montag, 8. August 2011 19:20:25 UTC+2 schrieb Steven W. Orr: if (( debug )) then _debug() { $@ # I do question whether this is a viable construct, versus # eval $@ } else _debug() { : } fi on bash-hackers.org I found this, which I think is the ultimate method to write a debug-function: _debug() { if $whatever_test_you_prefer; then _debug() { $@ } else _debug() { : } fi _debug $@ } they call it collapsing functions: http://wiki.bash-hackers.org/howto/collapsing_functions Just a quick response here, ifdef style is C code not compiled into the compiled program if it is not defined or chosen to be enabled. This in turn, prevents the CPU from wasting cycles testing if/then statements, etc... Tracing your suggestion, again, functions are read in each time the script is run even if debug=0, wasting CPU cycles memory. (Please correct me if I'm wrong here.) Think the previous one or two examples did seem to closely as possible mimic/copy ifdef style. The link looks interesting though, think I'll check it out! -- Roger http://rogerx.freeshell.org/
Re: saving bash.....
On 08/10/2011 10:39 PM, Linda Walsh wrote: Chet Ramey wrote: If not, then wouldn't $((( ))) be turned into $( (( )) ), meaning the arith returns a status, and not the calculation. (I've tested this, and this is the case. Then I said: It sounded to me like $(( )) would be translated into $( () ), turning off arithmetic expansion. Did I read that ___incorrectly__? Yes, you read it incorrectly. POSIX is saying that _if_ you want to guarantee command substitution of a subshell (that is, $() with a leading ( as the first item of the command to run), then use spaces. But if you want to guarantee arithmetic expansion, then you _have_ to start with $((; and that if you start with $((, then arithmetic expansion takes precedence. If not, [i.e. if I read it correctly] then wouldn't $((( ))) be turned into $( (( )) ), meaning the arith returns a status, and not the calculation. (I've tested this, and this is the case). Remember, $((body)) is treated as arithmetic expansion if body looks like arithmetic, and is only turned into $( (body)) otherwise (here, your body is '()'). POSIX' recommendation to add space is for the case of turning ambiguous $((body)) into definite command substitution $( (body)); you do not add space after the first '(' when you want arithmetic. ;-) ? (no insult intended! honest...just asking you (and others) to take a deep breath and not be reactive to what they think I'm am saying but try to focus on what I'm really trying (without great success, but I keep trying!) to say... Same here - I think we're all trying to be civil and helpful, and while emotions sometimes rise to the surface, hopefully everyone around is recognizing the underlying fact that no one here is intentionally trying to be malicious. I don't find it useful to have (()) cause exceptions. It's not a useful construct -- having it do so means it has to be programmed around. (()) is a useful construct, when used correctly; best designed for the condition of a loop expression where the loop will terminate when the count finally evaluates to 0. It does the same parsing and operation as $(()), except that instead of resulting in numeric output, it results in a change to $?. And once you realize that (()) is the shorthand counterpart to 'expr', and therefore has the same effect on $? (where 0 gives $?=1, non-zero gives $?=0, and error gives $?1), then you can properly use this extension. Or, since it is an extension, you can just avoid it altogether, and write scripts more portably. It's not useful to have a function that is meant to return no value, -- if last calc'ed value was 0, to cause a script to failit may be POSIX, but I'm looking for bash that was useful to write script in and do some rudimentary programming with -- NOT a POSIX shell, I can get from Microsoft or any other vendor. If you want to use 'set -e', then you have to deal with arithmetic results of 0 setting $? to 1, whether the arithmetic results come from traditional 'expr' or extension '(())'. That's life with 'set -e'; my advice has always been to avoid 'set -e' as a crutch and instead do error checking yourself, since 'set -e' behavior is unintuitive by design. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org
Explanations of Changes in Bash 4.0 @ http://wiki.bash-hackers.org
Great website (http://wiki.bash-hackers.org) explaining the changes in bash-4.* along with all other versions. (The web pages also note it's not a full list of changes.) In the past, I've scanned Bash's ChangeLog and it didn't provide any meaningful explanations, just very brief details. (It would be grueling to have to reread a beginner entry book on Bash to just learn 4.0 feature additions.) -- Roger http://rogerx.freeshell.org/ signature.asc Description: Digital signature
Re: Warning (HTML included to show prog shipped w/syntax highlighting).
On Wed, Aug 10, 2011 at 03:23:47PM -0700, Linda W wrote: 1 #!/bin/bash 2 30 31 # trace control for subs 32 declare -ix Allow_Trace=$((( 33 _D_LowLevel | 34 _D_Provides | 35 _D_ 36 ))) I cannot for the life of me figure out what you are trying to do here. Why are you writing $((( at all? Is _D_LowLevel a variable or a command name? Are you trying to write a pipeline of commands, or a bunch of bit-wise ORs? If you want a pipeline, use $(a|b|c). If you want bit-wise arithmetic, use $((a|b|c)). If you want an unreadable mess, continue as you are doing.
Re: Explanations of Changes in Bash 4.0 @ http://wiki.bash-hackers.org
On Thu, Aug 11, 2011 at 03:48:51AM -0800, Roger wrote: Great website (http://wiki.bash-hackers.org) explaining the changes in bash-4.* along with all other versions. (The web pages also note it's not a full list of changes.) In the past, I've scanned Bash's ChangeLog and it didn't provide any meaningful explanations, just very brief details. (It would be grueling to have to reread a beginner entry book on Bash to just learn 4.0 feature additions.) ... just needs a Print button for printing only the relevant text instead of all markups and comments. ;-) -- Roger http://rogerx.freeshell.org/
Re: Re: Inline `ifdef style` debugging
On Thu, Aug 11, 2011 at 12:23:00AM -0700, pjodrr wrote: they call it collapsing functions: http://wiki.bash-hackers.org/howto/collapsing_functions The first time you run chatter(), the function redefines itself based on the value of verbose. Thereafter chatter doesn't check $verbose anymore, it simply is. Further calls to the function reflect its collapsed nature. If verbose is unset, chatter will echo nothing, with no extra effort from the developer. The problem with this is that you can't switch to the other function later. unset verbose chatter $i ... verbose=1 chatter $j Here, the first call to chatter blows away the test of $verbose, so the next time we call it, the fact that we've set verbose=1 is ignored. We're stuck in non-verbose mode forever.
Aw: Re: Re: Inline `ifdef style` debugging
Am Donnerstag, 11. August 2011 14:13:27 UTC+2 schrieb Greg Wooledge: The problem with this is that you can't switch to the other function later. this is intended. The idea is to call a script with a debug or no-debug option. So for the runtime of the script the debug() function does not change. Here, the first call to chatter blows away the test of $verbose, so the next time we call it, the fact that we've set verbose=1 is ignored. We're stuck in non-verbose mode forever. if you want a different behaviour you have to test for $verbose everytime the chatter() is called which was to be avoided. cheers
Re: Bash source repository
2011-05-30, 06:34(+00), Michael Witten: [...] Ben, it is generally a good idea to maintain the `Cc' list unless explicitly asked. Beware that the bash mailing list also has a usenet interface (gnu.bash.bug) which has no notion of recipients let alone Cc. -- Stephane
Re: bug: return doesn't accept negative numbers
2011-08-08, 13:55(-07), Linda Walsh: [...] and both 'exit' and 'return' should return error ERANGE if --posix is set, and -1 is given. Iinvalid option doesn't make as much sense, in this situtation, if it was -k or -m, sure...but in this case, it's a fact that --posix artificially limits exit values apart from what is allowed in most prog langs (which accept negative, but still return results 0xff), so for Posix, it's a matter of disallowing a 'normal range', vs. it being an invalid option [...] POSIX doesn't prevent a shell from accepting -1 (or for doing anything like eject a cd or output an error or turn red upon return -1). It just says an *application* should not use return -1, that is that if one wants to write a portable script, she shouldn't use return -1. Many POSIX shells accept return -1 $ ksh93 -c 'f() return -1; f; echo $?' 255 $ pdksh -c 'f() return -1; f; echo $?' -1 $ zsh -c 'f() return -1; f; echo $?' -1 $ posh -c 'f() return -1; f; echo $?' return: invalid option -- '1' 1 $ posh -c 'f() return -- -1; f; echo $?' -1 $ mksh -c 'f() return -1; f; echo $?' mksh: return: -1: unknown option 1 $ mksh -c 'f() return -- -1; f; echo $?' -1 But as you can see the result varies, so one shouldn't use return -1 if one wants to be portable accross POSIX shells. Also note: $ zsh -c 'f() return -1; f; echo $?' -1 $ zsh -c 'f() return -1; (f); echo $?' 255 That is even in shells that support arbitrary numbers for return, as soon as they are cast to exit status, they are 255ed. -- Stephane
Re: [OT] Re: feature request: option to start script not from the very beginning of file
2011-08-02, 23:41(+02), mhenn: Am 02.08.2011 15:55, schrieb Stephane CHAZELAS: [...] What about: #! /bin/bash - :||:\#__END__ whatever you like here #__END__ [...] Why did you use :||: ... and not just :... ? when testing it, it doesn't make any difference: [...] Without :||, it does create a temporary file, fill it and set it as standard input to the : command. With :||:, that does not happen because the second : is not run since the first one succeeded. $ strace bash -c $':\\E\nE' | grep tmp stat(/tmp, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=12288, ...}) = 0 stat(/tmp, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=12288, ...}) = 0 access(/tmp, W_OK)= 0 statfs(/tmp, {...}) = 0 open(/tmp/sh-thd-1312368098, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3 open(/tmp/sh-thd-1312368098, O_RDONLY) = 4 unlink(/tmp/sh-thd-1312368098)= 0 $ strace bash -c $':||:\\E\nE' | grep tmp $ -- Stephane
Re: equivalent of Linux readlink -f in pure bash?
2011-08-9, 09:24(+00), Stephane CHAZELAS: 2011-08-9, 11:44(+10), Jon Seymour: Has anyone ever come across an equivalent to Linux's readlink -f that is implemented purely in bash? (I need readlink's function on AIX where it doesn't seem to be available). [...] What about: readlink_f() ( link=$1 max_iterations=40 while [ $max_iterations -gt 0 ]; do max_iterations=$(($max_iterations - 1)) dir=$(dirname -- $link) || exit base=$(basename -- $link) || exit dir=$(cd -P -- $dir pwd -P) || exit link=${dir%/}/$base if [ ! -L $link ]; then printf '%s\n' $link exit fi link=$(ls -ld -- $link) || exit link=${link#* - } done printf 2 'Loop detected\n' exit 1 ) Sorry, it's wrong if there are relative paths in symlinks (or trailing newlines). fixed_cmd_subst() { eval ' '$1'=$('$2'; ret=$?; echo .; exit $ret) set -- $1 $? '$1'=${'$1'%??} ' return $2 } readlink_f() ( link=$1 max_iterations=40 while [ $max_iterations -gt 0 ]; do max_iterations=$(($max_iterations - 1)) fixed_cmd_subst dir 'dirname -- $link' || exit fixed_cmd_subst base 'basename -- $link' || exit cd -P -- $dir || exit link=${PWD%/}/$base if [ ! -L $link ]; then printf '%s\n' $link exit fi fixed_cmd_subst link 'ls -ld -- $link' || exit link=${link#* - } done printf 2 'Loop detected\n' exit 1 ) -- Stephane
Re: equivalent of Linux readlink -f in pure bash?
2011-08-09, 11:29(+02), Bernd Eggink: On 09.08.2011 03:44, Jon Seymour wrote: Has anyone ever come across an equivalent to Linux's readlink -f that is implemented purely in bash? You can find my version here: http://sudrala.de/en_d/shell-getlink.html As it contains some corrections from Greg Wooledge, it should handle even pathological situations. ;) [...] function getlink # ([-l] path) Why use the ksh syntax instead of the standard one? { # Path of the file a symbolic link is pointing to. # -l: follow link chain, print last target # no option: print 1st target unchanged typeset dir file last link opt oldPWD=$PWD ret=0 (( OPTIND = 1 )) while getopts l opt do case $opt in (l) last=1 ;; esac done shift $(( OPTIND - 1 )) file=$1 if [[ $last ]] # last link then while true do dir=$(dirname $file) What if $file starts with -? [[ ! -d $dir ]] { ret=1 break } # remove slashes at end while [[ $file == */ ]] do file=${file%/} done What if $file is / file=${file##*/}# file name command cd -P $dir What if that command fails? [[ ! -h $file ]] break What if there are symlinks in the path components? link=$(command ls -l -- $file; printf x) Good point about command substitution discarding trailing newlines. I forgot that in the solution I gave. link=${link%$'\nx'} remove=$file - file=${link#*$remove} done printf %s\n $PWD/$file command cd $oldPWD What if $oldPWD has blanks or wildcards? elif [[ ! -h $file ]] # 1st link then printf %s\n $file else link=$(ls -l $file) printf %s\n ${link##*- } What about trailing newlines here and links with - in their path. fi return $ret What if $IFS contains 0 or 1? } declare -fc getlink What's the -c about? -- Stephane
Re: Is bash dying or dead (was Re: 4.1 is $((( ))) an 'official operator, if $(( )) isn't?
On 8/10/11 10:59 PM, Clark J. Wang wrote: How can people write stable scripts in an enironment of constant change? This is creating the exact opposite of what POSIX is supposed to help! I found the similar problem. Bash has changed a lot since 2.05b which is the 1st version of bash I've used. That's fine for everyday interactive use but introduces some incompatibility for scripts. Keep in mind that bash-2.05b was released over nine years ago. Things change in nine years. -- ``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: Mailcheck during completion
On 8/11/11 6:23 AM, Martin von Gagern wrote: Hi! I often get a bash message about new mail during command line completion. Steps to reproduce: Type ls ~/.bas and press tab. Expected result: Command line completed to ls ~/.bash or whatever is right. Actual result: If new mails have arrived, the mail check is performed when pressing tab, rendering the whole command line like this: $ ls ~/.basYou have mail in /var/mail/user h This is a real problem for both readability and subsequent editing of the command line. I suspect that you have a completion defined for `ls' and it's running a command or process substitution that's causing the mail check. Can you run `set -x', then attempt the completion again and post the results? -- ``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: Mailcheck during completion
Hi Chet, thanks for the swift reply! On 11.08.2011 15:54, Chet Ramey wrote: I suspect that you have a completion defined for `ls' and it's running a command or process substitution that's causing the mail check. Can you run `set -x', then attempt the completion again and post the results? Yes, there is a completion function for ls coming from the _longopt function from the bash-completion project at debian: http://anonscm.debian.org/gitweb/?p=bash-completion/bash-completion.git;a=blob;f=bash_completion;h=66019379fe1e9ef9b1010bff53a0dc1baf4e73d9;hb=7c81ef895455d0f7543c65789ff62808e7465578#l1540 With -x enabled, I see several subprocess lines, i.e. lines indented by two + instead of one. Some triggered by eval, others by $(...). I wonder why this breaks things. After all, those subshells should never print a prompt, should never even look for interactive input. But I take it you've got your reasons to suspect them. Can this be fixed? Greetings, Martin signature.asc Description: OpenPGP digital signature
Re: Mailcheck during completion
On 8/11/11 10:35 AM, Martin von Gagern wrote: Hi Chet, thanks for the swift reply! On 11.08.2011 15:54, Chet Ramey wrote: I suspect that you have a completion defined for `ls' and it's running a command or process substitution that's causing the mail check. Can you run `set -x', then attempt the completion again and post the results? Yes, there is a completion function for ls coming from the _longopt function from the bash-completion project at debian: http://anonscm.debian.org/gitweb/?p=bash-completion/bash-completion.git;a=blob;f=bash_completion;h=66019379fe1e9ef9b1010bff53a0dc1baf4e73d9;hb=7c81ef895455d0f7543c65789ff62808e7465578#l1540 With -x enabled, I see several subprocess lines, i.e. lines indented by two + instead of one. Some triggered by eval, others by $(...). I wonder why this breaks things. After all, those subshells should never print a prompt, should never even look for interactive input. But I take it you've got your reasons to suspect them. Can this be fixed? It's hard to say without a better idea of the problem. I suspected either eval or command substitution because they cause re-entry into the shell parser. I don't suspect command substitution because that explicitly turns off interactive mode, but eval does not. I'll see if I can run something simple to reproduce 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: equivalent of Linux readlink -f in pure bash?
On 09.08.2011 16:54, Stephane CHAZELAS wrote: 2011-08-09, 09:50(-04), Steven W. Orr: [...] *) To remove the trailing slashes, instead of while [[ $file == */ ]] do file=${file%/} done file=${file##*/}# file name just say file=${file%${file##*[!/]}} [...] file=${file%${file##*[!/]}} Same problem with / being changed to though. This has been fixed. Also getlink() now outputs paths always in normalized form. Any feedback appreciated! Bernd -- http://sudrala.de
Re: Re: Inline `ifdef style` debugging
On Thu, Aug 11, 2011 at 08:13:27AM -0400, Greg Wooledge wrote: On Thu, Aug 11, 2011 at 12:23:00AM -0700, pjodrr wrote: they call it collapsing functions: http://wiki.bash-hackers.org/howto/collapsing_functions The first time you run chatter(), the function redefines itself based on the value of verbose. Thereafter chatter doesn't check $verbose anymore, it simply is. Further calls to the function reflect its collapsed nature. If verbose is unset, chatter will echo nothing, with no extra effort from the developer. The problem with this is that you can't switch to the other function later. unset verbose chatter $i ... verbose=1 chatter $j Here, the first call to chatter blows away the test of $verbose, so the next time we call it, the fact that we've set verbose=1 is ignored. We're stuck in non-verbose mode forever. OK. Now I see the collapsing, and it seems more like a hidden collapse rather then an immediately apparent collapse from an initial stance after reading/tracing. When tracing this function, I was thinking the function would be read each time the top function was called. In reality, the function is read once during the first read in of the function (or on script execution), as such, doesn't look like anymore if/thens are called after the first reading of the function. It just is after the first reading. Guess I could put a little reminder comment when I use collapsible functions to remind me of this effect, as well as others reading/tracing the script. -- Roger http://rogerx.freeshell.org/
Re: Re: Inline `ifdef style` debugging
On Thu, Aug 11, 2011 at 12:38:17PM -0800, Roger wrote: OK. Now I see the collapsing, and it seems more like a hidden collapse rather then an immediately apparent collapse from an initial stance after reading/tracing. When tracing this function, I was thinking the function would be read each time the top function was called. I'd call it replacing the function with a different one. And yes, at first glance it looks like the function is defining a new function (with the same name) recursively, in preparation for calling it; but apparently not. It's wiping itself out so the *next* call gets the new function.
Re: bug: return doesn't accept negative numbers
On Mon, Aug 8, 2011 at 8:42 AM, Bob Proulx b...@proulx.com wrote: People sometimes read the POSIX standard today and think it is a design document. Let me correct that misunderstanding. It is not. POSIX is an operating system non-proliferation treaty. Love it! jon.
Re: Mailcheck during completion
On 8/11/11 10:44 AM, Chet Ramey wrote: It's hard to say without a better idea of the problem. I suspected either eval or command substitution because they cause re-entry into the shell parser. I don't suspect command substitution because that explicitly turns off interactive mode, but eval does not. I'll see if I can run something simple to reproduce it. It's eval. Try the attached patch. 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/ *** ../bash-4.2-patched/parse.y Fri Feb 25 12:07:41 2011 --- parse.y Thu Aug 11 19:02:26 2011 *** *** 2500,2504 is the mail alarm reset; nothing takes place in check_mail () except the checking of mail. Please don't change this. */ ! if (prompt_is_ps1 time_to_check_mail ()) { check_mail (); --- 2498,2502 is the mail alarm reset; nothing takes place in check_mail () except the checking of mail. Please don't change this. */ ! if (prompt_is_ps1 parse_and_execute_level == 0 time_to_check_mail ()) { check_mail ();
Re: bug: return doesn't accept negative numbers
` Stephane CHAZELAS wrote: 2011-08-08, 13:55(-07), Linda Walsh: [...] and both 'exit' and 'return' should return error ERANGE if --posix is set, and -1 is given. Iinvalid option doesn't make as much sense, in this situtation, if it was -k or -m, sure...but in this case, it's a fact that --posix artificially limits exit values apart from what is allowed in most prog langs (which accept negative, but still return results 0xff), so for Posix, it's a matter of disallowing a 'normal range', vs. it being an invalid option [...] POSIX doesn't prevent a shell from accepting -1 (or for doing anything like eject a cd or output an error or turn red upon return -1). It just says an *application* should not use return -1, that is that if one wants to write a portable script, she shouldn't use return -1. Many POSIX shells accept return -1 $ ksh93 -c 'f() return -1; f; echo $?' 255 $ pdksh -c 'f() return -1; f; echo $?' -1 $ zsh -c 'f() return -1; f; echo $?' -1 $ posh -c 'f() return -1; f; echo $?' return: invalid option -- '1' 1 $ posh -c 'f() return -- -1; f; echo $?' -1 $ mksh -c 'f() return -1; f; echo $?' mksh: return: -1: unknown option 1 $ mksh -c 'f() return -- -1; f; echo $?' -1 But as you can see the result varies, so one shouldn't use return -1 if one wants to be portable accross POSIX shells. Also note: $ zsh -c 'f() return -1; f; echo $?' -1 $ zsh -c 'f() return -1; (f); echo $?' 255 That is even in shells that support arbitrary numbers for return, as soon as they are cast to exit status, they are 255ed. Displaying -1 or 255 is fine. -1 would be an enhancement, but certainly not expected as it isn't clearly that the real value is an 8-bit integer... Only the broken shells that attempt to validate options for return (despite, it being documented to have none), return invalid values. I would deduce that it is only non-posix compliant shells that return '1', ... as they are trying to validate return's options (which doesn't take any)...