# Q:  What is /bin/[ ?



## byrnejb (Jun 17, 2020)

In /bin I see this:

```
ls -l /bin
total 1298
-r-xr-xr-x  2 root  wheel   23672 Nov  1  2019 [
-r-xr-xr-x  1 root  wheel   23672 Nov  1  2019 cat
-r-xr-xr-x  1 root  wheel   15400 Nov  1  2019 chflags
-r-xr-xr-x  1 root  wheel   27672 Nov  1  2019 chio
-r-xr-xr-x  1 root  wheel   19488 Nov  1  2019 chmod
-r-xr-xr-x  1 root  wheel   27744 Nov  1  2019 cp
. . .
```

What is /bin/[?


----------



## SirDice (Jun 17, 2020)

test(1)


```
# ls -ali /bin/test /bin/\[
159227907 -r-xr-xr-x  2 root  wheel  12584 Jun 17 13:40 /bin/[
159227907 -r-xr-xr-x  2 root  wheel  12584 Jun 17 13:40 /bin/test
```
Both files have the same inode number, which means they're hardlinked.

These are syntactically the same:

```
[ -f /some/file ] && cat /some/file
```


```
test -f /some/file && cat /some/file
```


----------



## kpedersen (Jun 17, 2020)

Yeah, in the early days it looked like shell "syntax" but was actually an external program.

I think most shells now provide the [ themselves rather than calling out to an external program.
That UNIX idea always seems really flexible but horribly inefficient to me.


----------



## SirDice (Jun 17, 2020)

kpedersen said:


> I think most shells now provide the [ themselves rather than calling out to an external program.


As far as I know only bash and related do this,  and  they use  the double notation for that ( `[[` )


----------



## kpedersen (Jun 17, 2020)

SirDice said:


> As far as I know only bash and related do this,  and  they use  the double notation for that ( `[[` )



Hmm, now I am not sure. Looking at the test manpage (https://www.freebsd.org/cgi/man.cgi?test)

"Some shells may provide a builtin test command which is similar or  identical to this utility.  Consult the builtin(1) manual page."

The builtin(1) manpage mentions that sh has a built in [ whereas csh doesn't. And the one on Linux:

"NOTE: your shell may have its own version of test and/or [, which usually supersedes the version described here.  Please refer to your shell's documentation for details about the options it supports."

I assumed this meant that use of the internal one was implicit.


----------



## SirDice (Jun 17, 2020)

kpedersen said:


> Hmm, now I am not sure.


Great, now I'm not sure either 

Ok, I was  close with bash, it's the Bourne shell that has it builtin:

```
[       A built-in equivalent of test(1).
```
As bash is a Bourne shell derivative it stands to reason bash has it too. Likely other Bourne shells like zsh will too.


----------



## Hakaba (Jun 17, 2020)

Si in test code, there is a code like :
if ($0 ='[') search the ']' character
But this is a test... 
That made my day, thanks


----------



## Eric A. Borisch (Jun 17, 2020)

You’re looking for builtin(1).


----------



## Eric A. Borisch (Jun 17, 2020)

And you can always use `execsnoop` from sysutils/dtrace-toolkit to see what executables are actually being run. (`/bin/[` doesn’t launch for `[` in either bash or sh from a quick test.)


----------



## Mjölnir (Jun 17, 2020)

RTFM `man builtin` builtin(1) for what is external and -- yes, built-in 
And use eval(1) in your scripts when the shell does not do what you want but what you told her, and you reach the point you feel like you could run out on the street and start a fight with the next innocent stranger who passes by occasionally...


----------



## Mjölnir (Jun 17, 2020)

and do not use bash scripts. It's not portable.


----------



## Eric A. Borisch (Jun 18, 2020)

mjollnir said:


> and do not use bash scripts. It's not portable.



* Unless there is a good reason (some feature makes what you are doing much cleaner to do / more maintainable) and you understand the limitations. (I can’t recall the last time I ran into a system where bash wasn’t available, even if not installed by default.)


----------

