Linux

如何以事務方式複製文件?

  • April 8, 2021

我想將一個文件從 A 複製到 B,它可能位於不同的文件系統上。

還有一些額外的要求:

  1. 副本全有或全無,崩潰時沒有部分或損壞的文件 B 留在原處;
  2. 不要覆蓋現有文件 B;
  3. 不要與同一命令的並發執行競爭,最多一個可以成功。

我認為這很接近:

cp A B.part && \
ln B B.part && \
rm B.part

但是如果 B.part 存在(即使使用 -n 標誌), cp 也會違反 3. 隨後 1. 如果其他程序“贏得”cp 並且連結到位的文件不完整,則可能會失敗。B.part 也可能是一個不相關的文件,但我很高興在這種情況下不嘗試其他隱藏名稱就失敗了。

我認為 bash noclobber 有幫助,這是否完全有效?有沒有辦法在沒有 bash 版本要求的情況下獲得?

#!/usr/bin/env bash
set -o noclobber
cat A > B.part && \
ln B.part B && \
rm B.part

跟進,我知道一些文件系統無論如何都會失敗(NFS)。有沒有辦法檢測這樣的文件系統?

其他一些相關但不完全相同的問題:

跨文件系統的近似原子移動?

mv 在我的 fs 上是原子的嗎?

有沒有辦法將文件和目錄從 tempfs 原子移動到 eMMC 上的 ext4 分區

https://rcrowley.org/2010/01/06/things-unix-can-do-atomically.html

rsync做這項工作。預設情況下會創建一個臨時文件O_EXCL(僅在使用 時才禁用--inplace),然後renamed覆蓋目標文件。用於--ignore-existing不覆蓋 B(如果存在)。

在實踐中,我在 ext4、zfs 甚至 NFS 掛載上從未遇到過任何問題。

別擔心,noclobber是標準功能

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