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.)

link|improve this question

60% accept rate
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
feedback

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
link|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 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 Mar 16 '11 at 0:42
feedback

Your Answer

 
or
required, but never shown

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