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.

What does the "inplace" modification of a file e.g. via sed -i or perl -i mean?
My question is about how this inplace modification is done. Is the file copied the modification is done in the copy and then replace the original? Or is the original file somehow being modified in place?

share|improve this question
    
Have a look at backreference.org/2011/01/29/in-place-editing-of-files for a detailed explanation of this topic. –  scy Jul 23 at 8:31

2 Answers 2

sed creates a temporary file, writes the output into that file, and then renames the temporary file over the top of the original.

You can watch what happens using strace:

$ strace -e trace=file sed -i -e '' a
execve("/usr/bin/sed", ["sed", "-i", "-e", "", "a"], [/* 34 vars */]) = 0
<...trimmed...>
open("a", O_RDONLY)                     = 3
open("./sedxvhRY8", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
rename("./sedxvhRY8", "a")              = 0
+++ exited with 0 +++

This logs all the file operations sed makes: it creates a new file (safely with O_CREAT|O_EXCL), writes the data into it, and then moves it back over the top of my original file a.

sed -i accepts a suffix to use for a backup, and in that case it moves the original out of the way first (rather than renaming over the top). That argument is mandatory in most BSD seds. In this case, there's a brief time when there's no file by the right name in the directory at all.

perl in recent versions opens the input file, then deletes it and creates a new file with the same name:

open("a", O_RDONLY)               = 3
unlink("a")                       = 0
open("a", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4

When you delete (unlink) a file you already have open you retain access to it for as long as you keep the handle around, so it can keep reading the data out of the deleted file. In this way perl writes directly into the output file, rather than into a temporary file: no additional file is created, but if you read the file during the process you'll get partial content, unlike with sed's approach. There's also a brief time when there's no file with the right name, which is at the start of the process rather than the end (as in sed -i .bak).


Both sed and perl will:

  • Replace a symbolic link with an ordinary file.
  • Break hard links.
  • Preserve group ownership if possible.
  • Create the file with your default group (or the group of the parent directory if that directory has the setgid bit) if it was owned by a group you're not in and you're not root.
  • Preserve file ownership if you're root.
  • Preserve basic permissions.
  • Preserve setuid and setgrp bits, if the resulting group is the same as the group it started in.
  • Preserve the sticky bit.
  • Not preserve xattrs.

sed will:

  • Preserve ACLs (On Linux; I don't know about others).

perl will:

  • Not preserve ACLs.

The above is true on Linux with GNU sed and Mac OS X with its (FreeBSD-derived) sed.

share|improve this answer

In additional to @Homer's answer, from perldoc perlrun:

specifies that files processed by the "<>" construct are to be edited in-place. 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, following these rules:

If no extension is supplied, no backup is made and the current file is overwritten.

If the extension doesn't contain a *, then it is appended to the end of the current filename as a suffix. If the extension does contain one or more * characters, then each * is replaced with the current filename.

And remember that, no soft link or hard link is preserved:

Note that because -i renames or deletes the original file before creating a new file of the same name, UNIX-style soft and hard links will not be preserved.

Finally, the -i switch does not impede execution when no files are given on the command line. In this case, no backup is made (the original file cannot, of course, be determined) and processing proceeds from STDIN to STDOUT as might be expected.

This also explains why you must use -i with -p option, or use a explicit print statement if you want to edit inplace with perl:

# Opps, file will be truncated, becomes empty
$ perl -i.bak -ne 's/123/qwe/' file

# Right way
$ perl -i.bak -ne 's/123/qwe/;print' file

# Or
$ perl -i.bak -pe 's/123/qwe/' file
share|improve this answer

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.