我想知道是否有任何方法可以仅在目标不存在时移动文件 - 换句话说,仅当不会导致覆盖时才移动文件。
mv --update
似乎首先是解决方案,但是,如果源路径的时间戳比目标新,则移动将覆盖它,并且在移动之前通过修改时间戳来规避此问题的所有尝试都将失败。
我需要这种行为来实现一个简单的基于文件的锁,其中“锁”文件的存在表明已获取锁。
答案1
您可以将 rsync 与以下--ignore-existing
开关结合使用:
skip updating files that exist on receiver
但是,我认为这不是原子的。您可以创建咨询锁定以flock
确保流程你控制(协作进程)不会写入它。但另一个进程仍然可以。
锁定文件而不冒其他进程干扰的风险的唯一方法是使用强制锁定挂载文件系统。来自<linux_kernel_source>/Documentation/filesystems/mandatory-locking.txt
:
什么是强制锁定?
强制锁定是内核强制执行的文件锁定,与用于保证进程之间顺序访问文件的更常见的协作文件锁定相反。文件锁定是使用 flock() 和 fcntl() 系统调用(以及 lockf() 库例程,它是 fcntl() 的包装器)应用的。通常,进程有责任检查要更新的文件上的锁定,然后再应用自己的锁定、更新文件并再次解锁。最常用的例子(在 sendmail 的情况下,也是最麻烦的)是访问用户的邮箱。邮件用户代理和邮件传输代理必须防止同时更新邮箱,并防止在更新邮箱时读取邮箱。
在理想世界中,所有进程都会使用并遵守合作或“建议”锁定方案。然而,这个世界并不完美,而且有很多编写糟糕的代码。
答案2
如果您在同一个文件系统上,请使用link()
和unlink()
代替mv
:
$ touch src
$ ln src dest && rm src
$ ls
dest
$ touch src2
$ ln src2 dest && rm src2
ln: creating hard link `dest': File exists
$ ls
dest src2
答案3
来自 open(2) 手册页:
想要使用锁文件执行原子文件锁定且需要避免依赖 NFS 对 O_EXCL 支持的可移植程序可以在同一文件系统上创建一个唯一文件(例如,合并主机名和 PID),并使用 link(2) 链接到该锁文件。如果 link(2) 返回 0,则锁定成功。否则,对唯一文件使用 stat(2) 检查其链接数是否已增加到 2,在这种情况下锁定也成功。