0

On Ubuntu-like linux, the default .bashrc file contains a line:

[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

Then why is SHELL=/bin/sh lesspipe grammatically correct? What page of man bash can I know the meaning of this statement? To me, this statement seems the same as, for example,

ls echo

, which is invalid. Also,

abc=hello echo $abc

makes no error but outputs null.

I couldn't find any relevant information in man bash though I tried some /<expression> search command on less. Could anyone please tell me the interpretations of the command?


Note: I've read the post "Can you explain eval expression in the default .bashrc" but got nothing.

ynn
  • 870
  • @steeldriver Thank you. Actually my post seems duplicate. But how did you find the post you cited? Before I post this entry, I surfed the internet, but couldn't find that. I would like to know not to repeat the same mistake. – ynn Aug 13 '18 at 15:30
  • it's no biggie, I guess my search-fu is just stronger ;) The relevant section of the bash man page is probably SHELL GRAMMAR - Simple Commands where it says A simple command is a sequence of optional variable assignments followed by blank-separated words and redirections, and terminated by a control operator. but unless you're a syntax weenie that's rather hard to recognize IMHO – steeldriver Aug 13 '18 at 15:34
  • @steeldriver Thank you. I should have first read through the chapter of SHELL GRAMMAR in man bash. – ynn Aug 13 '18 at 16:12

1 Answers1

4

As steeldriver said, SHELL=/bin/sh lesspipe is a simple command, which is defined as a sequence of:

  • optional variable assignments (here SHELL=/bin/sh), followed by...
  • blank-separated words and redirections (here lesspipe), terminated by...
  • a control operator, which includes a newline character.

Your first example:

ls echo

is actually a valid command: only the first word is treated as a command to execute, the rest are given to that command as parameters¹.

In the case of a ls command, if there is a sub-directory named echo in the current directory, its contents will be listed; if there is a non-directory named echo, its name will be displayed². If neither is true, the command will return an error and display a No such file or directory error message.

Your second example:

abc=hello echo $abc

is again a simple command with a variable assignment, but it also includes a variable expansion ($abc). The EXPANSION chapter of man bash defines the various kinds of expansion and their order of operations.

After the command line has been split into words, the shell checks for expansions:

  • brace expansion: nothing applicable
  • tilde expansion: nothing applicable
  • parameter and variable expansion: here $abc is replaced by the current value of shell or environment variable named abc. But since this command line has not been executed yet, the variable assignment earlier on the line (abc=hello) is not in effect yet. As a result, $abc is replaced by whatever value abc had before, or an empty string if it was not set. The empty string is then removed completely since it was not quoted.
  • command substitution: nothing applicable
  • arithmetic expansion: nothing applicable
  • word splitting: the only candidate for this would have been the result of the $abc variable expansion, but there is nothing to split in a null string.
  • pathname expansion: nothing applicable

Once the expansions are done, the variable abc in the environment of the to-be-started utility is set to value "hello" and the command echo is executed. It outputs just a single blank line.


¹ strictly speaking, ls is also passed as argument, as its argv[0]. ls uses that argument to know how it was invoked, uses it as well in the error messages it outputs, but doesn't consider it as an option or file to act upon.

² if it is a symbolic link, but its target can't be resolved, some ls implementations will however output an error message as if the file didn't exist

telcoM
  • 96,466
  • Thank you for your detailed answer. Is the command executed in sub-shell? Some answers of the post of which my post was judged as duplicate say the "simple command" is the same as (export var=value command). However, the chapters of Simple Commands and SIMPLE COMMAND EXPANSION don't refer to it. – ynn Aug 13 '18 at 16:17
  • @ynn The COMMAND EXECUTION ENVIRONMENT chapter told me it's true: *When a simple command other than a builtin or shell function is to be executed, it is invoked in a separate execution environment* – ynn Aug 13 '18 at 16:21