Sed with inplace editing changes group ownership of file

There is a little problem with sed's inplace editing mode -i. sed creates a temporary file in the same directory called sedy08qMA, where y08qMA is a randomly generated string. That file is filled with the modified contents of the original file. After the operation, sed removes the original file and renames the temporary file with the original filename. So it's not a true inplace edit. It creates a new file with permissions of the calling user and a new inode number. That behavior is mostly not bad, but for instance, hard links get broken.

However, if you want true inplace editing, you should use ed. It reads commands from the stdin and edits the file directly, without a temporary file (it's done over ed's memory buffer). A common practise is to use printf to generate the command list:

printf "%s\n" '1,$s/search/replace/g' wq | ed -s file

The printf command produces output as follows:

1,$s/search/replace/g
wq

Those two lines are ed commands. The first one searches for the string search and replaces it with replace. The second one writes (w) the changes to the file and quits (q). -s suppresses diagnostic output.


The -i parameter of sed works by creating a temp file during operation, then overwrite the actual file with the temp file in the end. That's the most likely the cause of the problem, since when creating the temp file ownership defaults to myuser:myuser

You can set the setgid bit on the parent directory(only if the parent directory is owned by group www-data), so that files created under this directory inherit the same group.
to do that:

chmod g+s parent-dir-of-your-file  

I think this is a very typical use of the setgid bit.


The use of ed instead of sed seems rather superfluous for this, given you have to pipe in an additional input. The distro I'm working on right now (CentOS 5.10) has the -c option for sed that utilizes 'copying' of the temp file rather than simply renaming it when used with the -i option. I've tested it and it worked perfectly, preserving the original owner and group when doing an inline edit. It does NOT preserve the modification time.

e.g., sed -ci -e '3,5d' file.txt

  • -c uses copy instead of rename (i.e., preserves ownership/group)
  • -i inline editing
  • -e script/expression to be executed

Not sure how widespread this option is for sed across other distros. Solaris 10 didn't have it, but Solaris doesn't have a lot of things I want.