Not evaluating an expression when using cat

I have one bash script that is designed to output another bash script. I am using cat. I want to evaluate some of the expressions in output script, but not others.

PROJECT=myproject

cat << EOF > create_dir.sh
#!/usr/bin/env bash

DATE=`date '+%y%m%d-%H%M'`
mkdir $PROJECT/\$DATE
EOF

The resulting create_dir.sh file looks like this:

#!/usr/bin/env bash

DATE=171123-1834

mkdir myproject/$DATE

The result that I want is this:

#!/usr/bin/env bash

DATE=`date '+%y%m%d-%H%M'`

mkdir myproject/$DATE

How can I modify this script so that the expression following DATE= is not evaluated, while at the same time ensuring that $PROJECT is evaluated?


You need to escape the '`' symbols since they mean "execute this code". So that line should look like:

DATE=\`date '+%y%m%d-%H%M'\`

cat << \EOF

If the label is quoted then the here document is taken as is. Or else quote the backquotes in the here document.

The relevant part of the manual page is:

If any part of word is 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, the character sequence \<newline> is ignored, and \ must be used to quote the characters \, $, and `.

Note that this solution will copy the here document verbatim; to have some expansions done and others not done the only solution is to use \ to quote those constructions which are not be expanded.