sed 原地替換檔案時遇到的趣事

鹹魚Linux運維發表於2023-11-04

哈嘍大家好,我是鹹魚

在文章《三劍客之 sed》中鹹魚向大家介紹了文字三劍客中的 sed

sed 全名叫 stream editor,流編輯器,用程式的方式來編輯文字

那麼今天鹹魚打算講一下我在用 sed 原地替換檔案時遇到的趣事

sed 讓檔案屬性變了?

有這麼一個普通檔案 test.txt ,內容如下:

[root@localhost /opt]# cat test.txt 
My name is Ammon
hello world!
hahahahaha

link_test.txt 是一個軟連結(Symbolic Link,也可以叫符號連結)檔案,指向 test.txt 檔案

軟連結檔案類似於 Windows 的快捷方式,它實際上是一個特殊的檔案。關於軟連結相關的內容這裡不過多介紹

如果我們對軟連結檔案內容進行修改,原始檔是會跟著改變的

當我使用 sed 對軟連結檔案link_test.txt 進行內容修改時,命令如下

[root@localhost /opt]# sed -i 's/Ammon/Edsion/g' link_test.txt 

有趣的現象發生了:使用 sed 對軟連結檔案link_test.txt 進行內容修改之後,原始檔test.txt內容沒有變化,軟連結檔案link_test.txt 的內容發生變化且變成了普通檔案


怎麼樣,是不是很神奇?sed 不但把檔案內容改了,還把檔案屬性也給改了

我們用 strace 工具來檢視一下在執行 sed 命令時作業系統做了哪些操作

strace 一個系統呼叫跟蹤工具,它會跟蹤並記錄命令執行期間的系統呼叫和訊號

[root@localhost /opt]# strace sed -i 's/Ammon/Edsion/g' link_test.txt > strace.log 2>&1

具體內容有點多,我們著重看下關鍵內容

由上圖可以知道,如果我們使用 sed 對一個檔案進行原地替換,需要有一個臨時檔案,sed 先把修改內容寫入到這個檔案,最後將檔案 rename 到原來的地方

那我的需求是對軟連結檔案 link_test.txt 進行內容修改,軟連結檔案屬性不變,且原始檔的內容也跟著改變,有沒有什麼方法呢?

也就是說我們希望命令在執行的時候能夠解析出來軟連結檔案後面指向的原始檔,直接對原始檔進行讀--處理--寫,最後 rename

sed 命令有一個選項 --follow-symlinks

--follow-symlinks: 
	follow symlinks when processing in place

我們在執行的時候加上這個選項:

[root@localhost /opt]# strace sed -i --follow-symlinks 's/Ammon/Edsion/g' link_test.txt > strace.log 2>&1


總結一下:

  • sed 替換的底層邏輯是把更新後的內容寫入一個臨時檔案裡面,然後再 rename 這個臨時檔案
  • 這樣就會使得如果沒有新增 –follow-symlinks 選項的話,對軟連結檔案進行 sed 操作就會使得軟鏈檔案變成了一個常規檔案(其實是那個臨時檔案重新命名導致的)
  • 如果要對軟連結檔案指向的原始檔進行操作,就需要新增 –follow-symlinks 選項

相關文章