12

Working on some bash functions, I didn't know source ... command, so I used eval $(cat ...) instead. Now I am wondering, whethe should I change every use of that, or is it just the same function?

They appear to work the same now, but maybe there will be some misleading differences later, I just want to know.

3 Answers 3

12

As already mentioned by @glennjackman, you'll want to quote the command substitution, else word splitting and pathname expansion will modify the content before it gets evaled. And while both will execute the commands from the file, there are differences.

  • When you source a script, various special shell variables will be modified, mainly the BASH_SOURCE, BASH_LINENO and FUNCNAME arrays. These are useful for printing error messages and debugging.

  • You can return from a sourced script with the return command (help return). With the eval, you won't get that effect. And similarly a RETURN trap will not be triggered for the eval.

  • When sourcing a script, you can pass arguments to it. You can't do that with that eval.

  • With the eval, the command substitution will read the entire content of the file into memory before passing it on to eval. When you source it, bash will read from the file as it goes.

7

eval $(cat ...) doesn't work in all cases. For example line breaks are converted to a single space by $(cat ...) before the content is processed by eval. This often breaks multi line statements like loops and here documents.

Try for example the following file with both methods:

for i in 1 2 3; do
 echo $i
done

cat<<EOF
a
b
c
EOF
2
  • 6
    If you use quotes, the whitespace will stay intact: eval "$(cat file)" Aug 11, 2012 at 21:39
  • 1
    Yes, that should work, too. But if one has to change the code anyway I's prefer source as it is a command made for specifically this. Aug 12, 2012 at 4:12
1

There's a nice summary of what source, eval and exec do here: http://www.unix.com/shell-programming-scripting/54347-bash-shell-exec-eval-source-looking-help-understand.html

I'd think your use of eval and source'ing the file will do the same thing. I'm not completely sure, though, that variables inside the subscript will behave the same in any case. I'd recommend using source if possible, because it's the more straightforward way to go and makes your code more readable.

1
  • 3
    comletely tangential: bash has a shorthand for $(cat file) -> $(< file) Aug 11, 2012 at 21:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .