Skip to main content
replaced http://unix.stackexchange.com/ with https://unix.stackexchange.com/
Source Link

In V7 Unix — where the Bourne shell made its debut — [ was called test, and it existed only as /bin/test. So, code you would write today as:

if [ "$foo" = "bar" ] ; then ...

you would have written instead as

if test "$foo" = "bar" ; then ...

This second notation still exists, and I find that it's more clear about what's going on: you are calling a command called test, which evaluates its arguments and returns an exit status code that if uses to decide what to do next. That command may be built into the shell, or it may be an external program.¹

[ as an alternative to test came later.² It may be a builtin synonym for test, but it is also provided as /bin/[ on modern systems for shells that do not have it as a builtin.

[ and test may be implemented using the same code. This is the case for /bin/[ and /bin/test on OS X, where these are hard links to the same executable.³ As a result, the implementation completely ignores the trailing ]: it doesn't require it if you call it as /bin/[, and it doesn't complain if you do provide it to /bin/test.⁴

None of that history affects [[, because there never was a primordial program called [[. It exists purely inside those shells that implement it as an extension to the POSIX shell.

Part of the distinction between "builtin" and "keyword" is due to this history. It also reflects the fact that the syntax rules for parsing [[ expressions is different, as pointed out in John1024's answerJohn1024's answer.⁵


Footnotes:

  1. When you look at it that way, it makes it clear why you must put spaces around [ in shell scripts, unlike the way parentheses and brackets work in most other programming languages. If the shell's command parser allowed if["$x"..., it would also have to allow iftest"$x"...

  2. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

  3. ls -i /bin/[ /bin/test

  4. But don't count on this behavior. The Bash built-in version of [ does require the closing ], and its built-in test implementation will complain if you do provide it.

  5. The builtin vs external command distinction may also matter for another reason: the two implementations may behave differently. This is the case for echo on many systems. Because there is only one implementation, no such distinction needs to be made for a keyword.

In V7 Unix — where the Bourne shell made its debut — [ was called test, and it existed only as /bin/test. So, code you would write today as:

if [ "$foo" = "bar" ] ; then ...

you would have written instead as

if test "$foo" = "bar" ; then ...

This second notation still exists, and I find that it's more clear about what's going on: you are calling a command called test, which evaluates its arguments and returns an exit status code that if uses to decide what to do next. That command may be built into the shell, or it may be an external program.¹

[ as an alternative to test came later.² It may be a builtin synonym for test, but it is also provided as /bin/[ on modern systems for shells that do not have it as a builtin.

[ and test may be implemented using the same code. This is the case for /bin/[ and /bin/test on OS X, where these are hard links to the same executable.³ As a result, the implementation completely ignores the trailing ]: it doesn't require it if you call it as /bin/[, and it doesn't complain if you do provide it to /bin/test.⁴

None of that history affects [[, because there never was a primordial program called [[. It exists purely inside those shells that implement it as an extension to the POSIX shell.

Part of the distinction between "builtin" and "keyword" is due to this history. It also reflects the fact that the syntax rules for parsing [[ expressions is different, as pointed out in John1024's answer.⁵


Footnotes:

  1. When you look at it that way, it makes it clear why you must put spaces around [ in shell scripts, unlike the way parentheses and brackets work in most other programming languages. If the shell's command parser allowed if["$x"..., it would also have to allow iftest"$x"...

  2. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

  3. ls -i /bin/[ /bin/test

  4. But don't count on this behavior. The Bash built-in version of [ does require the closing ], and its built-in test implementation will complain if you do provide it.

  5. The builtin vs external command distinction may also matter for another reason: the two implementations may behave differently. This is the case for echo on many systems. Because there is only one implementation, no such distinction needs to be made for a keyword.

In V7 Unix — where the Bourne shell made its debut — [ was called test, and it existed only as /bin/test. So, code you would write today as:

if [ "$foo" = "bar" ] ; then ...

you would have written instead as

if test "$foo" = "bar" ; then ...

This second notation still exists, and I find that it's more clear about what's going on: you are calling a command called test, which evaluates its arguments and returns an exit status code that if uses to decide what to do next. That command may be built into the shell, or it may be an external program.¹

[ as an alternative to test came later.² It may be a builtin synonym for test, but it is also provided as /bin/[ on modern systems for shells that do not have it as a builtin.

[ and test may be implemented using the same code. This is the case for /bin/[ and /bin/test on OS X, where these are hard links to the same executable.³ As a result, the implementation completely ignores the trailing ]: it doesn't require it if you call it as /bin/[, and it doesn't complain if you do provide it to /bin/test.⁴

None of that history affects [[, because there never was a primordial program called [[. It exists purely inside those shells that implement it as an extension to the POSIX shell.

Part of the distinction between "builtin" and "keyword" is due to this history. It also reflects the fact that the syntax rules for parsing [[ expressions is different, as pointed out in John1024's answer.⁵


Footnotes:

  1. When you look at it that way, it makes it clear why you must put spaces around [ in shell scripts, unlike the way parentheses and brackets work in most other programming languages. If the shell's command parser allowed if["$x"..., it would also have to allow iftest"$x"...

  2. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

  3. ls -i /bin/[ /bin/test

  4. But don't count on this behavior. The Bash built-in version of [ does require the closing ], and its built-in test implementation will complain if you do provide it.

  5. The builtin vs external command distinction may also matter for another reason: the two implementations may behave differently. This is the case for echo on many systems. Because there is only one implementation, no such distinction needs to be made for a keyword.

more clarifications
Source Link
Warren Young
  • 73.4k
  • 17
  • 182
  • 172

[ as an alternative to test came later.² It may be a builtin synonym for test, but it is also provided as /bin/[ on modern systems for shells that do not have it as a builtin.

[ and test may be implemented using the same code. This is the case for /bin/[ and /bin/test on OS X, where these are hard links to the same executable.³ As a result, the implementation completely ignores the trailing ]: it doesn't require it if you call it as /bin/[, and it doesn't complain if you do provide it to /bin/test.⁴

There is also a program on your system called /bin/[ by the way, which is used by shells that do not have [ built in.

As toPart of the distinction between "builtin" and "keyword," that"keyword" is purely due to this history. "Builtin" means that it is shadowing an external program, whereas "keyword" is a thingIt also reflects the fact that exists purely inside the shell. This distinction matters, because it affects behavior. Many shells' built-in echo implementation behaves differently fromsyntax rules for parsing /bin/echo[[, for example expressions is different, so you must be careful to make a distinction about whether you're talking about the builtin vs the external program. No such distinction needs to be made about a keywordas pointed out in John1024's answer.

  1. When you look at it that way, it makes it clear why you must put spaces around [ in shell scripts, unlike the way parentheses and brackets work in most other programming languages. If the shell's command parser allowed if["$x"..., it would also have to allow iftest"$x"...

  2. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

  3. ls -i /bin/[ /bin/test

  4. But don't count on this behavior. The Bash built-in version of [ does require the closing ], and its built-in test implementation will complain if you do provide it.

  5. The builtin vs external command distinction may also matter for another reason: the two implementations may behave differently. This is the case for echo on many systems. Because there is only one implementation, no such distinction needs to be made for a keyword.

[ as an alternative to test came later.²

[ and test may be implemented using the same code. This is the case for /bin/[ and /bin/test on OS X, where these are hard links to the same executable.³ As a result, the implementation completely ignores the trailing ]: it doesn't require it if you call it as /bin/[, and it doesn't complain if you do provide it to /bin/test.⁴

There is also a program on your system called /bin/[ by the way, which is used by shells that do not have [ built in.

As to the distinction between "builtin" and "keyword," that is purely due to this history. "Builtin" means that it is shadowing an external program, whereas "keyword" is a thing that exists purely inside the shell. This distinction matters, because it affects behavior. Many shells' built-in echo implementation behaves differently from /bin/echo, for example, so you must be careful to make a distinction about whether you're talking about the builtin vs the external program. No such distinction needs to be made about a keyword.

  1. When you look at it that way, it makes it clear why you must put spaces around [ in shell scripts, unlike the way parentheses and brackets work in most other programming languages. If the shell's command parser allowed if["$x"..., it would also have to allow iftest"$x"...

  2. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

  3. ls -i /bin/[ /bin/test

  4. But don't count on this behavior. The Bash built-in version of [ does require the closing ], and its built-in test implementation will complain if you do provide it.

[ as an alternative to test came later.² It may be a builtin synonym for test, but it is also provided as /bin/[ on modern systems for shells that do not have it as a builtin.

[ and test may be implemented using the same code. This is the case for /bin/[ and /bin/test on OS X, where these are hard links to the same executable.³ As a result, the implementation completely ignores the trailing ]: it doesn't require it if you call it as /bin/[, and it doesn't complain if you do provide it to /bin/test.⁴

Part of the distinction between "builtin" and "keyword" is due to this history. It also reflects the fact that the syntax rules for parsing [[ expressions is different, as pointed out in John1024's answer.

  1. When you look at it that way, it makes it clear why you must put spaces around [ in shell scripts, unlike the way parentheses and brackets work in most other programming languages. If the shell's command parser allowed if["$x"..., it would also have to allow iftest"$x"...

  2. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

  3. ls -i /bin/[ /bin/test

  4. But don't count on this behavior. The Bash built-in version of [ does require the closing ], and its built-in test implementation will complain if you do provide it.

  5. The builtin vs external command distinction may also matter for another reason: the two implementations may behave differently. This is the case for echo on many systems. Because there is only one implementation, no such distinction needs to be made for a keyword.

assorted clarifications
Source Link
Warren Young
  • 73.4k
  • 17
  • 182
  • 172

This second notation still exists, and makes it clearerI find that it's more clear about what's going on: you are calling an external programa command called test, which evaluates its arguments and returns a codean exit status code that if uses to decide what to do next.

An interesting point here is that because That command may be built into the shell, or it namesmay be an external program — which may be shadowed by a builtin —

[ isn't like the punctuation characters you see in other languages. You must put spaces around itas an alternative to separate it from the rest of the expression, for the same reason that you cannot write iftest"$x"test.. came later.²

The alias of[ and test tomay be implemented using the same code. This is the case for /bin/[ came later,¹ and /bin/test was extendedon OS X, where these are hard links to cope with the extrasame executable.³ As a result, the implementation completely ignores the trailing ] character: it doesn't require it if you call it as /bin/[, which exists purely for symmetryand it doesn't complain if you do provide it to /bin/test.

  1. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

    When you look at it that way, it makes it clear why you must put spaces around [ in shell scripts, unlike the way parentheses and brackets work in most other programming languages. If the shell's command parser allowed if["$x"..., it would also have to allow iftest"$x"...

  2. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

  3. ls -i /bin/[ /bin/test

  4. But don't count on this behavior. The Bash built-in version of [ does require the closing ], and its built-in test implementation will complain if you do provide it.

This second notation still exists, and makes it clearer what's going on: you are calling an external program called test, which evaluates its arguments and returns a code that if uses to decide what to do next.

An interesting point here is that because it names an external program — which may be shadowed by a builtin — [ isn't like the punctuation characters you see in other languages. You must put spaces around it to separate it from the rest of the expression, for the same reason that you cannot write iftest"$x"...

The alias of test to [ came later,¹ and test was extended to cope with the extra trailing ] character, which exists purely for symmetry.

  1. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

This second notation still exists, and I find that it's more clear about what's going on: you are calling a command called test, which evaluates its arguments and returns an exit status code that if uses to decide what to do next. That command may be built into the shell, or it may be an external program

[ as an alternative to test came later.²

[ and test may be implemented using the same code. This is the case for /bin/[ and /bin/test on OS X, where these are hard links to the same executable.³ As a result, the implementation completely ignores the trailing ]: it doesn't require it if you call it as /bin/[, and it doesn't complain if you do provide it to /bin/test.

  1. When you look at it that way, it makes it clear why you must put spaces around [ in shell scripts, unlike the way parentheses and brackets work in most other programming languages. If the shell's command parser allowed if["$x"..., it would also have to allow iftest"$x"...

  2. It happened around 1980. /bin/[ doesn't exist in my copy of Ancient Unix V7 from 1979, nor does man test document it as an alias. In the corresponding man page entry I have in a pre-release copy of the System III manual from 1980, it is listed.

  3. ls -i /bin/[ /bin/test

  4. But don't count on this behavior. The Bash built-in version of [ does require the closing ], and its built-in test implementation will complain if you do provide it.

assorted clarifications and detail additions
Source Link
Warren Young
  • 73.4k
  • 17
  • 182
  • 172
Loading
Source Link
Warren Young
  • 73.4k
  • 17
  • 182
  • 172
Loading