我有以下问题。我有两个目录,我将其称为dir1和dir2。它们都包含文件和子目录。它们都在同一个文件系统上。 dir1的内容是旧的,必须用dir2的内容替换。可以丢弃dir1的内容。但是,我需要这种替换以原子方式发生。我目前的解决方案如下。
mv dir1 dir1_backup; mv dir2 dir1; rm -rf dir1_backup
如果第一个命令失败,则第二个命令不会运行。这很好。但是,如果第二个命令失败怎么办? dir1不再存在,我处于无效状态。
实现这一目标的最佳方法是什么?有可能吗?
答案 0 :(得分:2)
如果第一个失败的话,我认为你的断言不会超过第二个命令会失败。如果mv dir1 dir1_backup
失败,则dir1仍然存在,mv dir2 dir1
将使dir2成为dir1的子目录。此外,由于您在第三个命令中将-f
传递给rm
,因此它将无法删除不存在的目录。
作为参考,有三个bash运算符(假设在这里使用bash)以及它们的作用:
如果您希望每个命令的执行都依赖于上一个命令的成功执行,那么您可能需要考虑以下内容:
mv dir1 dir1_backup && mv dir2 dir1 && rm -rf dir1_backup
如果目录的移动是您期望的失败模式,则在继续删除旧目录内容之前测试移动的返回值或测试是否存在预期目录可能是合理的。如果测试失败,则返回旧目录内容。整体操作将失败,但至少您不会处于无效状态。例如:
mv dir1 dir1_backup && \
mv dir2 dir1 && \
rm -rf dir1_backup || mv dir1_backup dir1
由于我们知道&&
仅在前一个命令成功退出时才执行以下命令,mv dir2 dir1
仅在mv dir1 dir1_backup
成功时执行。
此外,rm -rf dir1_backup
只有在dir2移动到dir1成功时才会执行。但是,如果最后一个退出代码(mv dir2 dir1
返回的代码如果失败)不为零,则||
运算符会导致mv dir1_backup dir1
执行。
希望有所帮助!如果需要澄清,请告诉我。
答案 1 :(得分:0)
在Linux上,您可以通过绑定将新目录安装在旧目录之上而摆脱困境。但是,在旧目录内的目录(例如,其当前工作目录)上具有打开句柄的进程仍然会遇到问题。
mount --bind dir2 dir1
类似的技巧将使您能够访问旧目录以进行清理。
如果此文件系统是通过NFS导出的,则可能需要确保将导出选项设置为允许遍历文件系统边界并在服务器上进行绑定安装。
其他* nix具有相似的功能,但尚未标准化。
答案 2 :(得分:0)
Linux提供了string subject = "SHD2018101 + SHD2018102 / 26 + SHD2018103";
StringCollection result = new StringCollection();
Regex regexObj = new Regex(@"(SHD\d+)");
Match matchResult = regexObj.Match(subject);
while (matchResult.Success) {
result.Add(matchResult.Groups[1].Value);
matchResult = matchResult.NextMatch();
}
系统调用,该系统调用带有renameat2
标志将交换2个对象:
RENAME_EXCHANGE