Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Bash is the only language I know where

  if cond; then x; else y; fi
does not do the same thing as

  if ! cond; then y; else x; fi
despite the the absence of any operator overloading.


Curious on this one, do you have an example showing it not working as expected?


  $ if   false; then :; else (if [ $? -eq 0 ]; then echo msg; fi); fi
  $ if ! false; then (if [ $? -eq 0 ]; then echo msg; fi); else :; fi
  msg


Your original claim is disingenuous.

Of course

  cond = false
  if cond; then x; else (if cond; then echo msg); fi
does not do the same thing as

  cond = true
  if cond; then (if cond; then echo msg); else x; fi
Bash is not somehow strange in this regard.


There's neither anything disingenuous about my claim. Bash's behavior is quite unique and unexpected to most people in the examples I showed. And I don't appreciate the attack.


That's correct behavior though.

You should do

if ARG=false

Then use $ARG not $? in the if statement.


It's the best kind of correct, yes.


It's a pretty bizarre use case, why would you need the second if statement, you already are in logic based on the return code

I can't think of an example of the if statement being confusing that isn't relying on $?


  error=0
  if ! some_command; then error=$?; bar; fi
  echo "blah"
  return $error


Yep that's a valid scenario, if you need more granularity than just fail or success then you will have to use a different method, e.g.

Status=0

Somecommand || status=$?

Then do logic based on status


Yep as a programing language shell is weird, I am sure you know this better than me, but I got nerd sniped by your snippet, and want say what I think is happening.

false the command returns 1, ! the command turns a 0 return code into a 1 and anything other than a zero into a 0, if is vaguely backwards from most languages in that it deals in return codes a rc of 0 is true and anything else is false

in the first case false has a rc of 1 this will execute the else list then the test command 1 is equal to 0(rc = 1 false list) so "msg" does not print

in the second case false(rc 1), !(rc 0), if(true list) now you check if rc is 0, it is and "msg" is printed.


Yeah. Basically instead of treating ! specially, Bash treats it like any other command that sets $? afterwards. And since it always succeeds, you always end up with $?=0 after it.

I don't know what kind of shell scripts the designers of this write, but the number of times I've wanted or found it helpful for ! to modify $? is has been exactly zero.

I am almost certain that >99% of people who write shell scripts do not find this intuitive.


> Yeah. Basically instead of treating ! specially, Bash treats it like any other command that sets $? afterwards. And since it always succeeds, you always end up with $?=0 after it.

I don't think that is true, consider:

  # if  false ; then  echo "true $?" ; else echo "false $?" ; fi
  false 1
  # if ! false ; then  echo "true $?" ; else echo "false $?" ; fi
  true 0
  # if ! ! false ; then  echo "true $?" ; else echo "false $?" ; fi
  false 1
Basically, $? evaluates to the full condition inside the "if" sentence.

One of the first things I learned when starting to use $? was to assign it to a variable asap if I needed to use it more than once.


Whoops, that's what I get for writing these when I'm sleepy. Yes of course ! doesn't always set the result to success, that wouldn't make any sense. I misspoke in that part. I meant to say Bash treats it like any other command that modifies $?, instead of treating it specially and preventing it from modifying that variable. Thanks.


Isn’t sql an other one?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: