sed
створює тимчасовий файл, записує вихід у цей файл, а потім перейменовує тимчасовий файл у верхній частині оригіналу.
Ви можете подивитися, що відбувається за допомогою 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 +++
Це записує всі файлові операції sed
: він створює новий файл (безпечно з O_CREAT|O_EXCL
), записує в нього дані, а потім переміщує їх у верхній частині мого оригінального файлу a
.
sed -i
приймає суфікс для використання для резервного копіювання, і в цьому випадку він спочатку переміщує оригінал (а не перейменування на верхній). Цей аргумент є обов'язковим у більшості BSD sed
. У цьому випадку короткий час, коли в каталозі взагалі немає файлу з правильним іменем.
perl
в останніх версіях відкривається вхідний файл, потім видаляється і створюється новий файл з тим же ім’ям:
open("a", O_RDONLY) = 3
unlink("a") = 0
open("a", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
Коли ви видаляєте ( unlink
) файл, який ви вже відкрили, ви зберігаєте доступ до нього так довго, поки ви не тримаєте ручку, щоб він міг читати дані зі видаленого файлу. Таким чином perl
записується безпосередньо у вихідний файл, а не у тимчасовий файл: додатковий файл не створюється, але якщо ви прочитаєте файл під час процесу, ви отримаєте частковий вміст, на відміну від sed
підходу 's. Існує також короткий час, коли немає файлу з правильним іменем, який знаходиться на початку процесу, а не в кінці (як в sed -i .bak
).
І те, sed
і perl
буде:
- Замініть символічне посилання звичайним файлом.
- Розривайте жорсткі зв’язки.
- Зберігайте право власності на групу, якщо можливо.
- Створіть файл зі своєю групою за замовчуванням (або групою батьківського каталогу, якщо у цьому каталозі є
setgid
біт), якщо ним належить група, у якій ви не входите, і ви не root.
- Збережіть право власності на файл, якщо ви root.
- Зберегти основні дозволи.
- Збережіть
setuid
і setgrp
біти, якщо отримана група збігається з групою, в якій вона почалася.
- Збережіть липкий шматочок.
- Не зберегти xattrs.
sed
буде:
- Збережіть ACL (у Linux; про інших я не знаю) .
perl
буде:
Сказане вище стосується Linux з GNU sed
та Mac OS X з його (похідним FreeBSD) sed
.