Is eval $(cat filename) the same as source filename?

Solution 1:

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.

Solution 2:

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

Solution 3:

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.