Edits:
- [2024-01-04 tor]: Its actually even more weird. Modern shells have a built-in implementation of
[
, but also usually include the program/bin/[
for historical reasons.
But hey, they are!
The colon
Historically, Bourne shells didn’t have true and false as built-in commands. true was instead simply aliased to :, and false to something like let 0.
And what do you know
: && echo ohye || echo nop
ohye
There are lots of creative use cases in the Stack overflow post, that never ocurred to me. I did however stumble across that if
statements need an expression inside the truthy branch to work, as I eagerly commented out some unescessary code.
This works.
bash
if [[ 1 == 1 ]]; then
echo yes
fi
yes
This does not!
bash
if [[ 1 == 1 ]]; then
# echo no
fi
bash: syntax error near unexpected token `fi'
Should have used the colon :
!
Some even sugggest you can use them for disabling variable commands or when you only want parameter expansions just for their side-effects ! 😵💫
And when you’re like “Wat, that’s weird.” - meet the single square bracket!
The single square bracket
On macos
, try this
ls -la /bin/ | head -n 5
total 4788
drwxr-xr-x 39 root wheel 1248 des 15 15:43 .
drwxr-xr-x 20 root wheel 640 des 15 15:43 ..
-rwxr-xr-x 2 root wheel 134224 des 15 15:43 [
-r-xr-xr-x 1 root wheel 1310224 des 15 15:43 bash
Say what?
which [
[: shell built-in command
Try it. (Edit: Note that this is not the built-in, but the equivalent [
-program of the shell)
"/bin/["
[: [missing ]
Its also called test
. The manual page leads with
TEST(1) General Commands Manual TEST(1)
NAME
test, [ — condition evaluation utility
SYNOPSIS
test expression
[ expression ]
DESCRIPTION
The test utility evaluates the expression and, if it evaluates to true,
returns a zero (true) exit status; otherwise it returns 1 (false). If
there is no expression, test also returns 1 (false).
So here’s an expression, let’s try it
"/bin/[" 1 = 1
[: missing ]
But it fails, as the final argument must be
]
.
"/bin/[" 1 = 1 ] && echo works
works
And as you’d expect, the following test fails
"/bin/[" 1 = 2 ] && echo works || echo fails
fails
The gift of bash
just keeps on giving! 🎁