Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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
share|improve this question
2  
Answer for a similar question from StackOverflow stackoverflow.com/questions/82256/… – Cristian Ciupitu Sep 3 '10 at 11:22
    
how can u dont have permission to a file you created yourself in tmp ? is it becuase of umask ? – k961 Feb 16 '15 at 4:40
    
@k961 I used chown to change the owner; it was just an example – Michael Mrozek Feb 16 '15 at 6:56
up vote 71 down vote accepted

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
share|improve this answer
14  
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 – Shawn J. Goff Dec 14 '10 at 15:20
echo test | sudo dd of=/tmp/foo
share|improve this answer
    
clever! this alleviates the need to do echo test | sudo tee /tmp/foo >/dev/null to discard the output. – Adam Katz Jan 14 '15 at 23:52
1  
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. – Adam Katz Jan 16 '15 at 6:32
4  
dd is reliable with the non-obscure bs=1 – umeboshi Jan 25 '15 at 3:50
    
@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. – syntaxerror Jan 29 at 17:38

tee is surely a good choice, but how about this?

sudo -i eval "echo test > /tmp/foo"

EDIT: as per hop's comment, there is a better way

sudo sh -c "echo test > /tmp/foo"
share|improve this answer
    
3 problems: eval instead of a simple sh -c; -i, which will change your working dir; running the whole command as root, which might change it's behaviour or may introduce an unnecessary risk. why did this ever get an upvote? – hop Aug 31 '10 at 10:38
    
I don't know why you seem to be annoyed by the upvote. Sure there can be bugs in my answers, I didn't say mine is the best, did I? – phunehehe Aug 31 '10 at 16:47
3  
you didn't, but it is misleading, generally bad and maybe even dangerous. – hop Aug 31 '10 at 20:24
    
COME ON! I fixed it, OK? What's the point of sacrificing you 1 rep for something that's already fixed? – phunehehe Dec 15 '10 at 3:16

While I agree, that | sudo tee is the canonical way, sometimes sed may work:

cat sudotest 
line 1

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

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

-i modifies the file in place. i1 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
share|improve this answer
    
This is worded like an Ancient Chinese riddle. Can't see to understand how this got so many upvotes. (hrmph) – syntaxerror Jan 29 at 17:36
    
@syntaxerror: Sir, I'm sorry, I'm not a native English speaker. If you specify what is unclear to you, I could try to improve my answer. Compared with 65 upvotes for Gert, 4 doesn't seem to be that many upvotes, either, don't you think? – user unknown Jan 30 at 1:35
    
Well I would be pretty satisfied with 4 :-D Your English is not bad at all. It's just worded in a kind of terse techie nerdspeak. I must guess you're a coder. Coders amongst each other will understand themselves perfectly that way, but a non-coder must think it's worded like...as said. – syntaxerror Jan 31 at 20:22

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|improve this answer
    
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. – richard Apr 15 '15 at 14:51
    
I can't think of any reason why I would want uncat when I have tee. – Wildcard Sep 29 '15 at 9:26
    
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. – Scott Feb 17 at 14:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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