Shell
交換文件名的最佳方法
我需要交換兩個文件(
file
和file_1
)的文件名。我正在使用以下程式碼。mv file .phfile mv file_1 file mv .phfile file
這可行,但非常有問題,有時甚至會導致數據失去。有一個更好的方法嗎?
Linux系統上的
renameat2
系統呼叫,帶有RENAME_EXCHANGE
標誌,應該做到這一點,這是一個聲稱使用它的cli工具。
在傳統的 Unix 系統中沒有交換文件的低級方法,因此您需要使用中間臨時名稱。為了穩健,請確保臨時名稱不會被任何其他程序使用(所以使用
mktemp
),並且它與其中一個文件位於同一文件系統上(否則這些文件將被不必要地複製而不是被重命名)。swap_files () { tmp_name=$(TMPDIR=$(dirname -- "$1") mktemp) && mv -f -- "$1" "$tmp_name" && mv -f -- "$2" "$1" && mv -f -- "$tmp_name" "$2" } swap_files file file_1
請注意,如果發生錯誤,第一個文件可能仍使用其臨時名稱,而第二個文件可能尚未移動,也可能尚未移動。如果您需要在中斷和崩潰的情況下保持穩健性,具有兩個臨時名稱的變體可能更容易從中恢復。
swap_files2 () { tmp_dir1=$(TMPDIR=$(dirname -- "$1") mktemp -d .swap_files.XXXXXXXXXXXX) && tmp_dir2=$(TMPDIR=$(dirname -- "$2") mktemp -d .swap_files.XXXXXXXXXXXX) && mv -f -- "$1" "$tmp_dir1/" && mv -f -- "$2" "$tmp_dir2/" && mv -f -- "$tmp_dir1/"* "$1" && mv -f -- "$tmp_dir2/"* "$2" && rmdir -- "$tmp_dir1" "$tmp_dir2" }
如果重新啟動時出現臨時目錄
.swap_files.????????????
,則意味著文件交換因電源故障而中斷。請注意,其中一個文件可能已經移動到位而另一個文件沒有,因此這裡的程式碼並不能處理所有情況,這取決於您想要什麼樣的恢復。現代 Linux 核心(自 3.15 起,於 2014 年 6 月發布)具有交換文件的系統呼叫:
renameat2(…, RENAME_EXCHANGE)
. 但是,似乎沒有一個常用的命令行實用程序。甚至 glibc 支持也是最近才添加的(2.28,於 2018 年 8 月發布)。