![如何创建并自动同步多个其他目录中的“合并”目录而不复制文件?](https://linux22.com/image/85909/%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E5%B9%B6%E8%87%AA%E5%8A%A8%E5%90%8C%E6%AD%A5%E5%A4%9A%E4%B8%AA%E5%85%B6%E4%BB%96%E7%9B%AE%E5%BD%95%E4%B8%AD%E7%9A%84%E2%80%9C%E5%90%88%E5%B9%B6%E2%80%9D%E7%9B%AE%E5%BD%95%E8%80%8C%E4%B8%8D%E5%A4%8D%E5%88%B6%E6%96%87%E4%BB%B6%EF%BC%9F.png)
如果我有一定数量的源目录,例如dir1
,dir2
... dir5
,如何创建一个自动同步的“合并”目标目录,其中包含源目录的所有文件和目录,但不涉及重复文件?
例如,我有以下源目录结构......
dir1/
- a
- b
dir2/
- b <-- Note the duplicate name, this one is more recent than dir1\b
- c
- dir2.1/ <-- Subdirectories present too.
- z
dir3/
- d
...“合并”时看起来像这样:
merge/
- dir2.1/
- z
- a
- b <-- Which one to show is based on modified time; most recent first.
- c
- d
(假设可能有数十个目录,其中包含数千个文件和子目录。)
源列表中的所有文件和目录应保持原样且不变,并且“合并”的目标目录不应占用额外的存储空间;即它可能只是由某个使用 inotify 的守护进程管理的所有符号链接。源目录还经常添加和删除文件和子目录,这也需要尽快反映在“合并”目录中。
一些用法示例:
我创建一个新文件 ,dir3/e
它会自动立即(或在几秒钟内)出现在merge
目录中。
我删除该文件dir1/a
,它立即(或几秒钟内)自动从merge
目录中消失。
我dir3/d
通过打开来编辑merge/d
我调用touch
它dir1/b
,因此它有一个更新的修改日期,dir2/b
因此merge/b
会自动更新以指向dir1/b
最新的日期。
我删除了dir1/b
,现在merge/b
将指向旧文件dir2/b
。
我尝试在其中创建一个文件,merge
但收到错误,因为这样做没有任何意义!
答案1
动态组合多个目录的内容正是联合安装(或联合文件系统)是关于。 Linux 上有多种实现,但通常的实现通过始终优先选择一个特定分支来解决分支之间的重复(例如,如果两者都存在,则dir2/file
始终优先dir1/file
)。然而我刚刚发现合并文件系统它具有更灵活的策略,特别是允许逐个文件选择最新文件。
设置:
mkdir dir1 dir2 merge
echo 1 >dir1/b; echo 2 >dir2/a
sleep 1
echo 1 >dir1/a; echo 2 >dir2/b; echo 2 >dir2/c
现在我们上车了。我们设置newest
文件访问(search
)和元数据修改(action
)的策略,并禁止创建(create
)(您可以将创建传递到其中一个分支,要么始终相同,要么基于可用磁盘空间,甚至随机!) 。
$ mergerfs -o category.action=newest,category.search=newest,category.create=erofs dir1:dir2:dir3 merge
$ head merge/?
==> merge/a <==
1
==> merge/b <==
2
==> merge/c <==
2
$ rm dir2/c
$ echo merge/?
a b
卸载:fusermount -u merge
答案2
这是我使用 bash 进行的修改。该解决方案的缺点是,在脚本运行期间,它会为每个副本创建符号链接,但由于最后一个文件名(具有相同名称)是具有最新时间戳的文件名,因此指向该文件的符号链接将保留。
在运行之前,请务必更改 MDIR(合并目录)和 BDIR 变量(初始目录/多个目录)。
MDIR=/tmp
(
BDIR="/tmp/ssh /etc/ssh"
for entry in $(find $BDIR -type f -exec stat --printf "%n,%Y\n" {} \;);do
fname=$(echo $entry | cut -f 1 -d ,)
tstamp=$(echo $entry | cut -f 2 -d ,)
bname=$(basename $fname)
echo $bname,$fname,$tstamp
done
) | sort -t, -nk 3 | \
while read entry;do
bname=$(echo $entry | cut -f 1 -d ,)
fname=$(echo $entry | cut -f 2 -d ,)
tstamp=$(echo $entry | cut -f 3 -d ,)
ln -svf $fname $MDIR/$bname
done
答案3
使用ln
创建-s
允许多个指针指向同一实际文件的符号 ( ) 链接将回答您的主要问题。然而,您的自动添加的使用示例现在已经满足了(但这可能对阅读您的标题和标题的其他人有用)。
ln -s src/of/actual/file merge_directory/pointer_link