0

Consider this little bash script:

#!/bin/bash
cmd="ls -rtl $1"
$cmd
eval $cmd

It prints the directory listing with some option set (just to make it different from a simple ls), twice. Both of the last two lines do the same thing, apparently. Is there some case, that I am not considering?

Why bother writing eval in front of the cmd?

steffen
  • 8,572
  • 11
  • 52
  • 90
  • See [BashFAQ #50](https://mywiki.wooledge.org/BashFAQ/050) for an extensive discussion of exactly how and why `$cmd` is broken. – Charles Duffy Aug 03 '23 at 19:13
  • They're different if `$cmd` contains shell metacharacters. – Barmar Aug 03 '23 at 19:13
  • (and if `$1` is a wildcard and the command is run in a directory where filenames aren't under the operator's control, `eval $cmd` is outright a major security risk) – Charles Duffy Aug 03 '23 at 19:13
  • Also see [BashFAQ/048](https://mywiki.wooledge.org/BashFAQ/048). – Dennis Williamson Aug 03 '23 at 19:14
  • See https://stackoverflow.com/questions/13365553/setting-an-argument-with-bash – Barmar Aug 03 '23 at 19:14
  • `eval $cmd` is _also_ broken. It needs to be `eval "$cmd"` **with the quotes** to be safe and correct (assuming that the value of the variable `$cmd` is itself known to be safe and correct, which it isn't when you substitute the value of `$1` into it as shown in the question; a less-bad alternative would be `cmd='ls -rtl "$1"'`, which defers that substitution until the last time the command goes through the parser). – Charles Duffy Aug 03 '23 at 19:14
  • ...with bash 5.0, you could also use `cmd="ls -rtl ${1@Q}"` to make something safe to `eval`, or with older versions, `printf -v cmd 'ls -rtl %q' "$1"` – Charles Duffy Aug 03 '23 at 19:16
  • Generally speaking, *don't* write `eval` in front of `$cmd`. Or ever. Ignore this advice, after adequate consideration, only when you thoroughly understand why I am giving it. – John Bollinger Aug 03 '23 at 21:32
  • Since you asked for an example of where the two would make a difference: Do a `cmd='echo $HOME'` and then try `$cmd` and `eval $cmd`. – user1934428 Aug 04 '23 at 06:54

0 Answers0