Shell

如何使 iconv 用轉換後的輸出替換輸入文件?

  • January 9, 2022

我有一個 bash 腳本,它列舉目錄中的每個 *.php 文件並應用於iconv它。這將在 STDOUT 中輸出。

由於添加-o參數(根據我的經驗)實際上可能在轉換發生之前寫入一個空白文件,我如何調整我的腳本以便它進行轉換,然後覆蓋輸入文件?

for file in *.php
do
   iconv -f cp1251 -t utf8 "$file"
done

這不起作用,因為iconv首先創建輸出文件(因為文件已經存在,所以它會截斷它),然後開始讀取它的輸入文件(現在是空的)。大多數程序都以這種方式執行。

為輸出創建一個新的臨時文件,然後將其移動到位。

for file in *.php
do
   iconv -f cp1251 -t utf8 -o "$file.new" "$file" &&
   mv -f "$file.new" "$file"
done

如果你的平台iconv沒有-o,你可以使用 shell 重定向來達到同樣的效果。

for file in *.php
do
   iconv -f cp1251 -t utf8 "$file" >"$file.new" &&
   mv -f "$file.new" "$file"
done

Colin Watson 的sponge實用程序(包含在Joey Hess 的 moreutils 中)自動執行此操作:

for file in *.php
do
   iconv -f cp1251 -t utf8 "$file" | sponge "$file"
done

這個答案不僅適用於任何過濾程序,iconv而且適用於任何過濾程序。一些特殊情況值得一提:

  • GNU sed 和 Perl-p可以-i選擇就地替換文件。
  • 如果您的文件非常大,您的過濾器只是修改或刪除某些部分,但從不添加東西(例如,,,greptrsed 's/long input text/shorter text/'並且您喜歡危險地生活,您可能希望真正修改文件(此處提到的其他解決方案創建一個新的輸出文件並將其移動到最後的位置,因此如果命令因任何原因中斷,原始數據將保持不變)。

引用自:https://unix.stackexchange.com/questions/10241