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.