Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

There seems to be some inconsistency that I am not able to understand regarding the bash shell.

If I execute:

ls;date;time

the results of the three queries are shown in sequence.

However, on interchanging date and time position, an error message pops up.

So if I execute:

ls;time;date

the error message says: bash: syntax error near unexpected token 'date'.

Can someone explain this?

share|improve this question
    
Your problem lies on time;date vs date;time. This seems to be a problem with pipeline in bash and last char generated with time output. Tested results in different terminal emulators are: - [Bash] $ date;time # [OK] $ time;date # [NotOK] bash:syntax error near unexpected token `date ' $ time # only error does not appear that it is the result of any date. - [Csh] $ date;time # [OK] $ time;date # [OK] - [Tcsh] $ date;time # [OK] $ time;date # [OK] - [Ksh] $ date;time # [OK] $ time;date # [OK] –  Mostafa Shahverdy Mar 6 '13 at 6:37
    
I have updated my answer with an explanation for the error message. Please check that this is the answer you were looking for. –  zwets Mar 8 '13 at 21:07

2 Answers 2

The time command in your pipeline is not the /usr/bin/time binary, but the bash time built-in. Compare man time with help time. The error you see is bash failing to parse time's argument. This must either be present or be a newline. It is a newline in your first example but absent in the second.

On the other hand, if you were to run

ls;date;'time'

or

ls;'time';date

where the quotes around 'time' revoke its status as a reserved word, then bash has no problems parsing the line. It now parses three commands in a list, which it will execute in sequence, and /usr/bin/time will report a usage error in either case.

Addendum

It was observed that though time ; date yields an error, time ; ; date does not. The likely explanation is that time ; is interpreted by bash as equivalent to time <newline>. The expression time ; ; date is then parsed as the list of time ; and date.

This is consistent with the observation that time ; and time ; ; are legal as well, the second being parsed as the singleton list containing time ; followed by the optional semicolon allowed after lists.

So another way of explaining why time ; date yields the error bash: syntax error near unexpected token 'date' is that time consumes the semicolon separating it from date. It can only do that because time is a bash reserved word.

share|improve this answer
    
Thanks for a nice explanation! But then again this behaviour looks like a bug to me: time is supposed to allow a NULL command, and semicolon is supposed to delimit lists, so IMO the time command shouldn't "consume" the semicolon after it. Other builtin commands (which can take arguments) do not exhibit this kind of behaviour. –  arrange Mar 8 '13 at 23:08
    
@arrange The complication is that time does not allow a null command (that would have disambiguated everything), it only allows a newline in place of the command. So time;date is indeed syntactically wrong in any interpretation. However time ; and time ; ; would then also be illegal. It can be debated whether time's behaviour is a bug or merely undocumented (it is internally consistent), but a bug report would definitely be in place. Would you be willing to file it? –  zwets Mar 8 '13 at 23:52
    
Well, I looked at the source (bash4.2:parse.y:lines 1205-1221) and there it says that time by itself can time a null command and then it does so by $$ = make_simple_command (x, (COMMAND *)NULL);. As for filing a bug I'm not sure 8) –  arrange Mar 9 '13 at 0:07

Bash treats the built-in time as a special case, when parsing command-lines.

As can be read in the bash manpage, the line as typed is first split into a list:

pipeline ; pipeline

where a pipeline is:

[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]

or in our case, simply:

time command

i.e. if time is present, then command must also be present.

[There is a special case that allows time to be followed by a newline, but that doesn't apply here]

So, in our case, we have:

time;date

being split into two pipelines:

1. time
2. date

and pipeline 1 is not well formed, since we have time without a command. Hence the error.

Note that the command-line time doesn't work here either:

$ /usr/bin/time;date
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]

bash parses this as expected, into 2 pipelines:

1. /usr/bin/time
2. date

and /usr/bin/time then refuses to run with no argument. Note that this is an error from /usr/bin/time not an error from bash.

The reason that back-tick works is that the back-tick stops time being interpreted as a special element within the pipeline.

i.e. with the back-tick:

`time`;date

it is parsed as two pipelines:

1. `time`
2. date

Remember that a pipeline, in our case, is:

[time] command

and the problem initially was that we had time with no command, which isn't allowed. But now we simply have the command:

`time`

without the preceding time, since the back-ticks mean that time is interpreted as the command, not as a preceding word.

So bash then runs its builtin time with no args, which is accepted. It produces no output, and we see no error.

Note that:

`time`

actually runs the result of the time built-in, i.e. it runs whatever the time built-in produces on stdout. But since time on its own doesn't write anything to stdout, it appears to work.

Finally, it's been noted that this works:

time ; ; date

which I can't explain, sadly :)

share|improve this answer
    
I think your explanation is better, but it still looks weird to me. ;date gives bash: syntax error near unexpected token ;, but time ;date gives bash: syntax error near unexpected token date, so it seems bash doesn't treat the command after the time builtin as ";date". Interestingly, time ; ; date works. –  arrange Mar 7 '13 at 20:59
    
yup, thanks @arrange, it's quite weird. I'll update the answer slightly. –  cdmackay Mar 7 '13 at 22:05
    
ok, @arrange, have rewritten. Still can't explain your last though... sigh. –  cdmackay Mar 7 '13 at 22:34
    
@cdmackay You are mixing up backticks and quotes. By quoting 'time' it loses its meaning as a reserved word. Backticking it makes it execute in a subshell whose output gets spliced into the command. This has nothing to do with the discussion. As a matter of fact, your example `time\';date proves the contrary of your claim: this should give an error by your reasoning because /usr/bin/time requires an argument. The reason it doesn't is because in the subshell in which it executes it is the reserved word time once again. –  zwets Mar 8 '13 at 6:06
    
@arrange Both are syntax errors and both are reported to be near the same place, so I don't see an inconsistency there. Once it enters syntax error land, you can't expect a parser to know its way out. If you would require that of a parser, then it must know not only the legal syntax, but also the syntax of every possible illegal construct, which is impossible by definition. –  zwets Mar 8 '13 at 6:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.