Using variables inside a bash heredoc

Jon picture Jon · Feb 8, 2011 · Viewed 113.7k times · Source

I'm trying to interpolate variables inside of a bash heredoc:

var=$1
sudo tee "/path/to/outfile" > /dev/null << "EOF"
Some text that contains my $var
EOF

This isn't working as I'd expect ($var is treated literally, not expanded).

I need to use sudo tee because creating the file requires sudo. Doing something like:

sudo cat > /path/to/outfile <<EOT
my text...
EOT

Doesn't work, because >outfile opens the file in the current shell, which is not using sudo.

Answer

Mark Longair picture Mark Longair · Feb 8, 2011

In answer to your first question, there's no parameter substitution because you've put the delimiter in quotes - the bash manual says:

The format of here-documents is:

      <<[-]word
              here-document
      delimiter

No parameter expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. [...]

If you change your first example to use <<EOF instead of << "EOF" you'll find that it works.

In your second example, the shell invokes sudo only with the parameter cat, and the redirection applies to the output of sudo cat as the original user. It'll work if you try:

sudo sh -c "cat > /path/to/outfile" <<EOT
my text...
EOT