mirror of
https://github.com/koalaman/shellcheck.git
synced 2025-10-03 19:29:44 +08:00
Updated SC2091 (markdown)
19
SC2091.md
19
SC2091.md
@@ -37,19 +37,24 @@ eval "$(make_command foo.html output/foo.html)"
|
|||||||
```
|
```
|
||||||
### Rationale:
|
### Rationale:
|
||||||
|
|
||||||
ShellCheck has detected that you have a command that just consists of a command substitution.
|
ShellCheck has detected that you have a command that just consists of a command substitution. This often happens when you want to run a command (possibly from a variable name), without realizing that `$(..)` is for capturing and not for executing.
|
||||||
|
|
||||||
This is typically done in order to try to get the shell to execute a command, because `$(..)` does indeed execute commands. However, it's also replaced by the output of that command.
|
For example, if you have this shell function:
|
||||||
|
|
||||||
When you run `echo "The date is $(date +%F)"`, bash evalutes the `$(..)`. The command then becomes `echo "The date is 2015-04-29"`, which writes out the string `The date is 2015-04-29`
|
sayhello() { echo "hello world"; }
|
||||||
|
|
||||||
The problem is when you use `$(date +%F)` alone as a command. Bash evaluates the `$(..)`, and the command then becomes `2015-04-29`. There is no command called `2015-04-29`, so you get `bash: 2015-04-29: command not found`.
|
Then `$(sayhello)` will:
|
||||||
|
|
||||||
Sometimes this results in this confounding `command not found` messages. Other times you get even stranger issues, like the example problematic code which always evaluates to false.
|
1. Run `sayhello`, capturing "hello world"
|
||||||
|
1. Run `hello world`, resulting in `bash: hello: command not found`
|
||||||
|
|
||||||
The solution is simply to remove the surrounding `$()`. This will execute the command instead of the command's output.
|
Meanwhile, just `sayhello` will:
|
||||||
|
|
||||||
If you instead have based a script around generating shell command strings, you can use `eval "$(cmd)"` to evaluate the output of a command as a second command. The benefit of using `eval` is that quotes, pipes, redirections, and other shell constructs will work as expected. Without the `eval`, all these will be treated as literal strings instead.
|
1. Run `sayhello`, outputting "hello world" to screen
|
||||||
|
|
||||||
|
Note that this is equally true if the command is in a variable, e.g. `x=sayhello; $($x)`.
|
||||||
|
|
||||||
|
If you *do* have a command that outputs a second command, similar to how `ssh-agent` outputs `export` commands to run, then you should do this via `eval`. This way, quotes, pipes, redirections, semicolons, and other shell constructs will work as expected. Note that this kind of design is best avoided when possible, since correctly escaping all values can be difficult and error prone.
|
||||||
|
|
||||||
### Exceptions:
|
### Exceptions:
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user