2

Once upon a time I used sed and tee combined to alter a privileged file in place. Because the shell itself doesn't have root privileges I had to get creative to write command output into files:

sed -r 'script' "/etc/hosts" | sudo tee "/etc/hosts" 1>/dev/null

At the time, this worked wonderfully. It was only after I started using my hosts file for ad blocking that I realised the pipe is limited to a buffer, after which tee will gladly overwrite the file and the rest of the file will disappear.

I also considered a much simpler version:

sed -r 'script' "/etc/hosts" > "/etc/hosts.tmp" && sudo mv "/etc/hosts.tmp" "/etc/hosts"

Unfortunately, this too won't work, since the file in question is a symlink. A mv would overwrite the symlink, as opposed to the file underneath.

My current solution is this:

sed -r 'script' "/etc/hosts" | sudo tee "/etc/hosts.tmp" 1>/dev/null &&
    sudo cat "/etc/hosts.tmp" | sudo tee "/etc/hosts" 1>/dev/null &&
    sudo rm "/etc/hosts.tmp"

Ew! How verbose!

Is there a cleaner way of doing this?

Serenity
  • 35,289
  • 20
  • 120
  • 115
J V
  • 11,402
  • 10
  • 52
  • 72
  • Useless use of `cat`: use `sudo tee /etc/hosts < /etc/hosts.tmp`. – chepner May 04 '16 at 17:56
  • Useless spam of useless saying. That wouldn't work because there's no guarantee `/etc/hosts.tmp` created through `sudo tee` is readable by the shell – J V May 04 '16 at 17:59
  • You're creating the file; there's no need to use `sudo` to create the file (nor is there any need to create the temporary file in `/etc` in the first place). – chepner May 04 '16 at 18:01

1 Answers1

3

If you're using GNU sed, you could use its -i in-place edition flag, so that the results of its execution is directly saved to the file it process. Then you just have to sudo the sed command and you should be fine.

Additionnaly to write the file rather than the link, use sed's --follow-symlinks flag.

In other cases, check this answer to a similar question on SO.

Community
  • 1
  • 1
Aaron
  • 24,009
  • 2
  • 33
  • 57
  • Yes but then I'll still need cleanup won't I? (And if sed kicks the bucket I'll have half a file) **Edit** Never mind, apparently the leftover files are only if you provide a suffix to `-i`. Though I wonder how it can tell the difference between a suffix and another flag... – J V May 04 '16 at 17:44
  • Actually I'm going to have to uncheck this answer - turns out `sed -i` has the same problem as `mv` - it's turning my symlink into a file! (I'll try readlink and realpath and when I find a combo that works I'll tick you and post in the question) – J V May 04 '16 at 17:56
  • @JV let me check if I can find something – Aaron May 04 '16 at 18:09
  • @JV see my edited answer, there's a `--follow-symlinks` flag that will solve your problem – Aaron May 04 '16 at 18:10