以自动方式移动目录

我有两个目录在同一个父目录。 调用父目录和子目录alphabravo 。 我想用bravoreplacealpha 。 最简单的方法是:

rm -rf alpha mv bravo alpha 

mv命令是primefaces的,但rm -rf不是。 在bash中有一个简单的方法来自动地用布拉沃代替阿尔法 ? 如果不是,有没有复杂的方法?

附录:

由此,如果该目录不存在很短的时间,这不是一个不可逾越的问题。 只有一个地方试图访问alpha,并在做任何关键的事情之前检查alpha是否存在。 如果不是,则会给出错误消息。 但是,如果有办法做到这一点,那就太好了。 :)也许有一些方法可以直接修改inode,或者…

Solutions Collecting From Web of "以自动方式移动目录"

如果你使用符号链接,你可以这样做:

假设alpha是目录alpha_1的符号链接,并且您希望将符号链接切换为指向alpha_2。 这是开关之前的样子:

 $ ls -l lrwxrwxrwx alpha -> alpha_1 drwxr-xr-x alpha_1 drwxr-xr-x alpha_2 

要使alpha指向alpha_2,请使用ln -nsf:

 $ ln -nsf alpha_2 alpha $ ls -l lrwxrwxrwx alpha -> alpha_2 drwxr-xr-x alpha_1 drwxr-xr-x alpha_2 

现在你可以删除旧的目录:

 $ rm -rf alpha_1 

请注意,这实际上并不是一个完全原子操作,但是它确实发生得非常快,因为“ln”命令既解除链接又立即重新创建符号链接。 你可以用strace验证这个行为:

 $ strace ln -nsf alpha_2 alpha ... symlink("alpha_2", "alpha") = -1 EEXIST (File exists) unlink("alpha") = 0 symlink("alpha_2", "alpha") = 0 ... 

您可以根据需要重复此过程:例如,当您有新版本时,alpha_3:

 $ ln -nsf alpha_3 alpha $ rm -rf alpha_2 

最终的解决方案是结合符号链接和重命名方法:

 mkdir alpha_real ln -s alpha_real alpha # now use "alpha" mkdir beta_real ln -s beta_real tmp # atomically rename "tmp" to "alpha" # use -T to actually replace "alpha" instead of moving *into* "alpha" mv -T tmp alpha 

当然,访问alpha的应用程序必须能够处理路径中的符号链接改变。

如果你指的是两个行动的原子,我不这么认为。 最接近的是:

 mv alpha delta mv bravo alpha rm -rf delta 

但是这仍然会有一个alpha窗口不存在的小窗口。

为了最大限度地减少任何尝试使用alpha的可能性,而不是在那里,你可以(如果你有权力):

 nice --20 ( mv alpha delta ; mv bravo alpha ) rm -rf delta 

这将在mv操作发生时大幅提升您的流程优先级。

如果像你在附录中所说的那样,只有一个地方检查alpha和它的错误(如果它不存在),那么你可以改变这个代码,不要马上出错,而​​要在短时间内再试一次(对于两个mv操作, ) – 这些重试应该可以缓解任何问题,除非您经常更换alpha。

使用单独的,保证的原子操作来充当信号量。

所以,如果创建和删除文件操作是原子的:

1)创建一个名为“semaphore”的文件。

2)当且仅当成功(不存在与现有文件冲突),执行操作(根据进程,处理alpha或移动目录)

3)信号量。

在这里,大卫的解决方案,这是完全原子接近…你遇到的唯一的问题是, -T选项为mv是非POSIX,所以某些POSIX操作系统可能不支持它(FreeBSD,Solaris等) 。… http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html )。 经过微小的修改,这种方法可以被改变为完全原子化的,并且可以跨所有POSIX操作系统移植:

 mkdir -p tmp/real_dir1 tmp/real_dir2 touch tmp/real_dir1/a tmp/real_dir2/a # start with ./target_dir pointing to tmp/real_dir1 ln -s tmp/real_dir1 target_dir # create a symlink named target_dir in tmp, pointing to real_dir2 ln -sf tmp/real_dir2 tmp/target_dir # atomically mv it into ./ replacing ./target_dir mv tmp/target_dir ./ 

例如通过: http : //axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/

SQLite第3版中的SQLite文档锁定和并发性部分对其升级的锁定协议进行了很好的描述,以便在崩溃后控制并发读取,独占写入和回滚。 其中一些想法适用于此。

这应该做的伎俩:

 mkdir bravo_dir alpha_dir ln -s bravo_dir bravo ln -s alpha_dir alpha mv -fT bravo alpha 

strace mv -fT bravo alpha显示:

 rename("bravo", "alpha") 

这对我来说看起来很原子。

我不相信有任何原子的方式来做到这一点。 你最好的办法是做这样的事情:

 mv alpha delme mv bravo alpha rm -rf delme 

即使您直接访问inode,仍然无法自动交换用户空间中的inode值。

担心操作的原子性质是没有意义的。 事情是,由其他任务访问alpha将不会是原子无论如何。

Oddthinking的信号量方法是唯一的方法。

如果你不能修改其他任务,那么你必须确保它没有运行之前进行更换。

需要注意的是,如果你的进程有任何alpha打开的文件,当这个移动/删除发生时,进程将不会注意到,当文件关闭并最终删除时,写入的任何数据都将丢失。

mv和ln可以用于原子操作。 我已经使用ln(1)以原子方式部署Web应用程序。

替换符号链接的正确方法是使用ln -nsf

 ln -nsf <target> <link_name> 

例如

 $ mkdir dir1 $ mkdir dir2 $ ln -s dir1 mylink $ ls -l mylink lrwxrwxrwx 1 phil phil 4 Nov 16 14:45 mylink -> dir1 $ ln -nsf dir2 mylink $ ls -l mylink lrwxrwxrwx 1 phil phil 4 Nov 16 14:46 mylink -> dir2 

你为什么不做这样的事情:

 rm -rf alpha/* mv bravo/* alpha/ rm -rf bravo/ 

这意味着 alpha中的所有东西都被销毁了,alpha 永远不会被删除,所有的内容都会被移动。