35

In bash I can create a script with a here-doc like so as per this site: http://tldp.org/LDP/abs/html/abs-guide.html#GENERATESCRIPT

(
cat <<'EOF'
#!/bin/bash
#? [ ] / \ = + < > : ; " , * | 
#/ ? < > \ : * | ”
#Filename="z:"${$winFn//\//\\}
echo "This is a generated shell script."
App='eval wine "C:\Program Files\foxit\Foxit Reader.exe" "'$winFn'"'
$App
EOF
) > $OUTFILE

If my $OUTFILE is a directory requiring sudo privileges where do I put the sudo command or what else can I do to make it work?

1
  • I suppose one solution is to generate the file to a temporary location and then move it with sudo to the proper location. Is that the most elegant way to do it?
    – D W
    Commented Dec 10, 2010 at 18:31

4 Answers 4

78

This is how I would do it:

sudo tee "$OUTFILE" > /dev/null <<'EOF'
foo
bar
EOF
4
  • How do you use this method to append to an existing file?
    – MountainX
    Commented Jul 21, 2013 at 4:07
  • 6
    @MountainX: tee -a appends to the file. Commented Jul 21, 2013 at 4:26
  • 2
    but this doesn't expand env variables ? Commented Jul 21, 2014 at 7:02
  • Mihai: That's correct, quoting the 'EOF' disables expansion.
    – Ti Strga
    Commented Apr 4, 2022 at 23:53
29

Just putting sudo before cat doesn't work because >$OUTFILE attempts to open $OUTFILE in the current shell process, which is not running as root. You need the opening of that file to happen in a sudo-ed subprocess.

Here's one way to accomplish this:

sudo bash -c "cat >$OUTFILE" <<'EOF'
#!/bin/bash
#? [ ] / \ = + < > : ; " , * | 
#/ ? < > \ : * | ”
#Filename="z:"${$winFn//\//\\}
echo "This is a generated shell script."
App='eval wine "C:\Program Files\foxit\Foxit Reader.exe" "'$winFn'"'
$App
EOF

This starts a sub-shell under sudo, and opens $OUTFILE from that more privileged subprocess, and runs cat (as yet another privileged subprocess). Meanwhile, the (less privileged) parent process pipes the here-document to the sudo subprocess.

8
  • This works for my minimum working example but not for my actual script. I have made my minimum working example sufficiently more complicated, can you help me with the new script?
    – D W
    Commented Dec 10, 2010 at 18:44
  • @D W: I'd unquoted your here-word, which may have been the source of your trouble. Sorry about that. Try re-quoting it, as shown in my updated answer. Commented Dec 10, 2010 at 18:58
  • @D W: have you tried the updated answer? It works with the newer code in your question. I just went and updated it again to actually include the code from your question. Commented Dec 10, 2010 at 19:06
  • interesting that the quotes make that much difference. Perfect, thanks.
    – D W
    Commented Dec 10, 2010 at 19:08
  • 2
    @D W: Yeah, I was surprised by this myself. From gnu.org/software/bash/manual/bashref.html#Redirections : "If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion." Useful maybe, but what a horrible syntax! My long-running theory is that most of bash syntax was designed around what was a syntax error in previous versions (with sh being the ancestral root). Commented Dec 10, 2010 at 19:31
1

You can also use dd for that:

sudo dd of="$OUTFILE" <<EOF
foo
bar
EOF
-1

None of the answers expanded environment variables since they use the subtle feature "Parameter substitution turned off" as described in: tldp.org/LDP/abs/html/here-docs.html - Example 19-7. (Thx to Jamie giving this pointer)

My workaround is leaving parameter substitution intact and use a tmp file and a sudo mv.

l_log=/var/log/server/server.log
l_logrotateconf=/etc/logrotate.d/server
tmp=/tmp/$$.eof
cat << EOF > $tmp
$l_log {
   rotate 12
   monthly
   compress
   missingok
   notifempty
}
EOF
sudo mv $tmp $logrotateconf
2
  • None of these answers worked ... Don't quote EOF. See tldp.org/LDP/abs/html/here-docs.html and jump to "Example 19-7. Parameter substitution turned off"
    – Jamie
    Commented May 29 at 17:47
  • I see - it is a feature not a bug - thank you for pointing out this subtle syntactic detail. I wander why i get down votes for this. Commented May 31 at 6:23

Not the answer you're looking for? Browse other questions tagged or ask your own question.