Take the 2-minute tour ×
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.

A friend of mine points out that if you do:

perl -pi.bak -e 's/foo/bar/' somefile

when "somefile" is actually a symlink, perl does just what the docs say it will do:

It does this by renaming the input file, opening the output file by the original name, and selecting that output file as the default for print() statements. The extension, if supplied, is used to modify the name of the old file to make a backup copy [...]

Which results in a new symlink "somefile.bak" pointing to the unchanged real file, and a new, changed regular file "somefile" with the changes.

In many cases, following the symlink would be the desired behavior (even if it leaves the correct location of the .bak file ambiguous). Is there a simple way to do this other than testing for symlinks in a wrapper and handling the case appropriately?

(sed does the same thing, for what that's worth.)

share|improve this question
1  
Call vim or emacs (I think both do follow symlinks)? Seriously, I fear the answer is to reimplement -p -i in your script. –  Gilles Mar 15 '11 at 21:20
add comment

1 Answer

up vote 5 down vote accepted

I wonder whether the small sponge general-purpose utility ("soak up standard input and write to a file") from moreutils will be helpful in this case and whether it will follow the symlink.

The author describes sponge like this:

It addresses the problem of editing files in-place with Unix tools, namely that if you just redirect output to the file you're trying to edit then the redirection takes effect (clobbering the contents of the file) before the first command in the pipeline gets round to reading from the file. Switches like sed -i and perl -i work around this, but not every command you might want to use in a pipeline has such an option, and you can't use that approach with multiple-command pipelines anyway.

I normally use sponge a bit like this:

sed '...' file | grep '...' | sponge file
share|improve this answer
    
Hey cool, that works. I suspect Gilles's comment above is the "real" answer, but since he didn't make it as an answer, and since I learned a new utility, I'll take this one. :) –  mattdm Mar 16 '11 at 0:26
    
But have you tested sponge for such a usage in practice? As for me: not yet. Could you please leave a comment stating whether it behaved in a test the way wanted here? Oh, I see the comment. Thanks for the confirmation! –  imz -- Ivan Zakharyaschev Mar 16 '11 at 0:28
    
— yes, I tried it before replying. When file in your example above is a symlink, the link is left alone and the real file changed. –  mattdm Mar 16 '11 at 0:38
    
@mattdm: Yes, thanks for the confirmation! (I noticed your words "that works" a bit later than I wrote my comment.) –  imz -- Ivan Zakharyaschev Mar 16 '11 at 0:42
add comment

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.