3 ms·
I always found it delightful how `if [ condition ]` works in bash, which, in case you don't know: the way `if <something>` works in bash is that <something> is
by OskarS 6y ago
I always found it delightful how `if [ condition ]` works in bash, which, in case you don't know: the way `if <something>` works in bash is that <something> is a command that runs like everything else in bash. If the command succeeds (i.e. if the return code for the process is 0), the body of the if executes.
So how does `if [ <condition> ]` work then? Is it some kind of special case? No! The way it works is that there's an executable named `[` in UNIX that that takes the condition expression as arguments, and returns "success" or "failure" depending on if the condition evaluates to true. It's right there in the filesystem at /bin/[
Now, some sticklers might argue that maybe not the greatest idea to spawn a process every time you need to evaluate an if statement, but I really do admire the UNIX purity of it: of COURSE that's how bash conditionals work! This is UNIX, after all! Why add an expression parser/evaluator to bash when you can just have it's own process for that? Do one thing and do it well!
- wkz 6y agoWhile it might not be a special case exactly, you most likely won’t see /bin/[ being executed either. Typically your shell will implement it as a built in command. Because as you say, spawning processes is expensive.
- mr-wendel 6y agoActually... it usually is a special case. For performance reasons there are some sneaky things Bash tends to do to avoid spawning lots of extra processes. In this case the `[` binary is more for backwards compatibility. You can verify this by writing a simple test script and doing (at least on Linux) "strace ./test.sh 2>&1 | grep exec" and observe no explicit call to that binary.
- tjoff 6y agoIt is neat, but it also trips up a lot of us in the beginning. Because at one point you instead write: 'if [condition]' and get weird errors. And you can't understand how suddenly you can't even do a simple if-statement. And there are tons of gotchas like that that made me terrified of bash. Even the simplest construct can attack you from any angle and the trial and error and distrust is everywhere. I'm getting better at it but for me and I guess many others, I just don't use bash enough to remember these quirks and the resulting experience is rather poor. Which is a shame! The savior for me was shellcheck. Instead of needing character-perfect memory of each construct and common snippet I can run shellcheck on it and it will tell me what common pitfall I might have stumbled upon and most importantly, why it is an issue. For a beginner I think it is an absolute must.
- cle 6y agoBecause Bash already has an expression parser/evaluator that it uses for this case, so now there isn't just one thing doing it, there are two, and you have to know when they are used and when they aren't. Honestly the idea that a certain benign-looking syntax could (but maybe not!) spawn some external subprocess is terrifying to me, and I don't find it delightful at all.
- rgrau 6y agoThere is some special casing in the ifs conditions though. Even if you `set -e`, the command in the test can fail and your script won't exit.