Redirecting stdout to a file you don't have write permission on

23,561

Solution 1

Yes, using tee. So echo test > /tmp/foo becomes

echo test | sudo tee /tmp/foo

You can also append (>>)

echo test | sudo tee -a /tmp/foo

Solution 2

To replace the content of the file with the output of echo (like the > shell redirection operator).

echo test | sudo dd of=/tmp/foo

To write into the file (at the beginning, though you can use seek to output at different offsets) without truncating (like the 1<> Bourne shell operator):

echo test | sudo dd of=/tmp/foo conv=notrunc

To append to the file (like >>), with GNU dd:

echo test | sudo dd of=/tmp/foo oflag=append conv=notrunc

See also GNU dd's conv=excl to avoid clobbering an existing file (like with set -o noclobber in POSIX shells) and conv=nocreat for the opposite (only update an existing file).

Solution 3

tee is probably the best choice, but depending on your situation something like this may be enough:

sudo sh -c 'echo test > /tmp/foo'

Solution 4

While I agree, that | sudo tee is the canonical way, sometimes sed (here assuming GNU sed) may work:

cat sudotest 
line 1

sudo sed -i '1iitest' sudotest && cat sudotest 
itest
line 1

sudo sed -i '$aatest' sudotest && cat sudotest 
itest
line 1
atest

-i modifies the file in place. 1i means insert before line 1. $a means append after last line.

Or copy to xclipboard:

somecommand | xclip
sudo gedit sudotest
move cursor to desired place, click middle mouse button to insert, save

Solution 5

I have been kicking around in the back of my mind ideas for a similar problem, and came up with the following solutions:

  • sudo uncat where uncat is a program that reads standard input and writes it to the file named on the command line, but I haven't written uncat yet.

  • sudocat the variant of sudoedit that I haven't written yet that does a cleaner sudo cat or sudo uncat.

  • or this little trick of using sudoedit with an EDITOR that is a shell script

    #!/bin/sh
    # uncat
    cat > "$1"
    

    which can be invoked as either |sudo ./uncat file or | EDITOR=./uncat sudoedit but that has interesting side-effects.

Share:
23,561

Related videos on Youtube

Michael Mrozek
Author by

Michael Mrozek

Updated on September 17, 2022

Comments

  • Michael Mrozek
    Michael Mrozek over 1 year

    When you attempt to modify a file without having write permissions on it, you get an error:

    > touch /tmp/foo && sudo chown root /tmp/foo
    > echo test > /tmp/foo
    zsh: permission denied: /tmp/foo
    

    Sudoing doesn't help, because it runs the command as root, but the shell handles redirecting stdout and opens the file as you anyway:

    > sudo echo test > /tmp/foo
    zsh: permission denied: /tmp/foo
    

    Is there an easy way to redirect stdout to a file you don't have permission to write to, besides opening a shell as root and manipulating the file that way?

    > sudo su
    # echo test > /tmp/foo
    
  • Shawn J. Goff
    Shawn J. Goff over 13 years
    Tee will also output to stdout; sometimes you don't want the contents filling the screen. To fix this, do echo test | sudo tee /tmp/foo > /dev/null
  • Adam Katz
    Adam Katz over 9 years
    clever! this alleviates the need to do echo test | sudo tee /tmp/foo >/dev/null to discard the output.
  • Adam Katz
    Adam Katz over 9 years
    I may have to take that back; dd is unreliable for that unless you're using obscure GNU-only options iflag=fullblock oflag=fullblock, which remove the elegance of this answer. I'll stick with tee.
  • umeboshi
    umeboshi over 9 years
    dd is reliable with the non-obscure bs=1
  • ctrl-alt-delor
    ctrl-alt-delor about 9 years
    cat takes a list of files to concatinate, therefore uncat should take a list of files to un concatinate to. It would have to use magic to decide how much to put in each file. Alternative name include dog, to-file, redirect.
  • Wildcard
    Wildcard over 8 years
    I can't think of any reason why I would want uncat when I have tee.
  • syntaxerror
    syntaxerror over 8 years
    @umeboshi But reliable only if you're experienced enough to know exactly what you're doing. Fordd can be fairly dangerous (if not to say: devastating) if only a slight mistake was made. So for new users, I'd rather recommend the tee method to be on the safe shore.
  • Scott - Слава Україні
    Scott - Слава Україні about 8 years
    Well, tee has the trivial drawback that it writes its stdin to its stdout — which is trivially mitigated by redirecting the stdout to /dev/null.  Other alternatives include dd of=/tmp/foo (mentioned in another answer), which writes status information to stderr, and cp /dev/stdin /tmp/foo.
  • edfuh
    edfuh over 7 years
    How will you do it with heredoc?
  • Michael Mrozek
    Michael Mrozek over 7 years
    I'm not sure what advantage not writing to stdout presents, but you could just redirect the output to /dev/null if it were an issue
  • user3299406
    user3299406 over 7 years
    Of course I can redirect to /dev/null, but the command is easier to read and type without the redirection. The advantage of not writing to stdout is that my terminal is not filled with rubbish.
  • user3299406
    user3299406 over 7 years
    I would not install a package to spare a redirection, but I regularly use sponge, so it is already there.
  • Stéphane Chazelas
    Stéphane Chazelas over 6 years
    @AdamKatz, in the case of dd of=file alone (without count/skip...), it is reliable. iflag=fullblock is not needed because here dd writes on output what it has read on input. It doesn't matter if it was not full blocks.
  • Andrew Henle
    Andrew Henle about 6 years
    Note that sed -i does not actually modify the file in place - it creates a temporary file and renames it on exiting. So you won't be able to do something like tail -f ... on the original file and see the output using sed -i ... while the pipeline is running
  • user unknown
    user unknown about 6 years
    @AndrewHenle: Yes, since the size may be increased or shrinked, and since that's probably the case for most sed invocations, and you can't even - afaik - write to the same location on SSDs it's only a pseudo 'in place' operation. As a non native english speaker, may I ask for a brief expression, which isn't so likely misinterpreted? Just -i creates a new file of same name or is there something more compact? I guess I like in place, because it explains the i. The gnu-sed manpage calls it in place too and the long flag is --in-place.