1

I have been reading the man pages for test(1), bash(1) and dash(1), but I can't figure out the meaning of this test :

[ `echo hi` > /dev/null ]

According to the man pages, there are two types of conditional expressions, primary and combined. Combined expressions are expressions combined of primaries.

I've gone through the list of primaries and none matches the syntax of the above expression. Can someone break it down for me?

gpo
  • 113
  • I'd be more interested in finding out why it works this way. The expression syntax used in my example doesn't match anything in the man pages. – gpo Apr 04 '13 at 22:47

2 Answers2

5

OK. I'm a bash novice, but: Though your question is clear, I'm not completely sure I get what you ask for. This is perhaps off mark. Please tell if so.

TEST IF "echo hi > /dev/null" is success

[ `echo hi` > /dev/null ]
| |   |   | |           |
| |   |   | |           +--- Last test argument
| |   |   | +--------------- Redirect standard out to /dev/null
| |   |   +----------------- Backtick - End Command Substitution
| |   +--------------------- echo hi
| +------------------------- Backtick - Start Command Substitution
+--------------------------- Test

If either echo or redirection fails, test fail, else success.

When a command is executed it has an exit code signifying success, 0, or error <> 0. Thus if either fails everything fails.

The pattern "[ ... ]" is not as in if (foo == bar), but [ is actually a command which require ] as last argument.

This also clarify why one need space after and before [ and ].

Runium
  • 28,811
  • I think that Stephane nailed it. I was expecting an interpretation error because the redirection is outside the command substitution. But, as Stephane noted, redirections may appear anywhere on the line. The rest is not very hard to figure out, but I wasn't very clear with my question either. Thank you for your answer anyway. – gpo Apr 05 '13 at 11:19
3

That's the same as:

[ `echo hi` ] > /dev/null

redirections may appear anywhere on the line.

Under normal condition, it is the same as

[ hi ]

Which itself is the same as:

true

That is a command that doesn't output anything and returns a success exit status.

The outcome may be different if:

  • the redirection fails, for instance if you've reached the limit of open files or haven't write access to /dev/null (which again shouldn't happen under normal conditions). In that case, the shell will return with a non-zero exit status and you'll see an error message, and the [ command will not be run.
  • The command substitution fails (for instance because you can't fork any more process or can't start a pipe because you've reached the max number of file descriptors). In that case, depending on the shell, many things may happen including the shell aborting.
  • if $IFS contains either h or i, then that will resolve to (for instance for IFS=h): [ '' i ], which is invalid and will cause [ to return an error and set the exit status to non-success.
  • possibly weirder things if [ or echo have been redefined to do something else like play a tune or reboot the computer.

All in all, that command doesn't make sense and has probably been written in the sole intent of confusing you.

  • This is a great analysis, thank you. Actually, the command comes from a typo I made (I meant to put the redirection inside the command substitution) and didn't expect it to execute, but it did. I wasn't aware of the fact that redirections may appear anywhere on the line. Would you have a reference for this? – gpo Apr 05 '13 at 11:10
  • @gpo, See the POSIX spec: A "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator. It's not uncommon to write things like < foo tr a b > bar or echo>&2 error for instance. – Stéphane Chazelas Apr 05 '13 at 12:16
  • But inside the test construct we have a conditional expression which is not the same as a "simple command", no? – gpo Apr 05 '13 at 12:43
  • Yes, [ is a command, generally builtin like echo or :. See this answer to another question about [ – Stéphane Chazelas Apr 05 '13 at 13:09