hug*_*omg 6 file-sharing files
如果我有一个大文件,我可以使用它ln
来制作不占用额外磁盘空间的“副本”。但是如果我不想要文件的精确副本怎么办?有没有办法通过一些修改来创建文件的新版本,而无需复制整个文件并使用两倍的磁盘空间?
我的动机是编辑来自 torrent 下载的 mp3 文件上的 id3 标签。我不想直接编辑下载的文件,因为这会弄乱播种,但我也不想复制文件并使用两倍的磁盘空间只是为了编辑一些 id3 标签的标题。
如果您使用的程序中没有内置功能,以某种方式将新信息覆盖在基本文件上,您必须在文件系统级别解决此问题,对使用该文件的应用程序透明。由于您的空间要求,版本控制系统是不够的,尽管它为您提供了多个版本。
您可以调查的一件事是将文件存储在 Btrfs 文件系统上,并将原始文件保存在一个“原始”快照中,并将更新版本保存在基于此快照的视图中。这应该适用于 ID3v1 标签(因为它们是文件的结尾)以及那些具有 ID3v2 标签¹的文件,只要它们有足够的保留空间进行更改并且不需要重写 MP3 文件。因此,只有为文件更改的实际块才会占用额外的磁盘空间。
如果您在原件中添加其他文件,则必须为cp --reflink src dst
稍后添加的所有文件进行明确。然后,您的下载将在派生视图上与原件和您的 id3 编辑器(例如 picard)和您的音乐播放器一起使用。该视图中未更改(或尚未更改)的文件看起来与原始文件完全相同。
示例(从一个 Btrfs 卷/data0
和一个test.mp3
文件开始/tmp
):
/data0$ btrfs subvolume create /data0/mp3org
Create subvolume '/data0/mp3org'
/data0$ cp /tmp/test.mp3 mp3org/
/data0$ btrfs subvolume snapshot /data0/mp3org/ /data0/id3update
Create a snapshot of '/data0/mp3org/' in '/data0/id3update'
Run Code Online (Sandbox Code Playgroud)
该文件test.mp3
现在在两个目录 (mp3org
和id3update
)中都可用:
/data0$ ls -l /data0/mp3org
total 7600
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:21 test.mp3
/data0$ ls -l /data0/id3update/
total 7600
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:21 test.mp3
Run Code Online (Sandbox Code Playgroud)
更改快照中的一个:
/data0$ id3v2 -c "This is a change" id3update/test.mp3
/data0$ ls -l /data0/mp3org
total 7600
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:21 test.mp3
/data0$ ls -l /data0/id3update/
total 7608
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:24 test.mp3
Run Code Online (Sandbox Code Playgroud)
文件大小没有改变,但第二个的内容改变了。这是因为注释确实适合原始文件中 id3v2 的保留空间。
/data0$ grep -F "is a change" mp3org/* id3update/*
Binary file id3update/test.mp3 matches
Run Code Online (Sandbox Code Playgroud)
复制原始子卷中的另一个文件,它不会出现在id3update
:
/data0$ cp /tmp/test.mp3 mp3org/abc.mp3
/data0$ ls -l mp3org/ id3update/
id3update/:
total 7600
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:24 test.mp3
mp3org/:
total 15200
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:28 abc.mp3
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:21 test.mp3
Run Code Online (Sandbox Code Playgroud)
制作一个明确的 reflink 副本:
/data0$ cp --reflink mp3org/abc.mp3 id3update/
/data0$ ls -l mp3org/ id3update/
id3update/:
total 15200
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:29 abc.mp3
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:24 test.mp3
mp3org/:
total 15200
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:28 abc.mp3
-rw-rw-r-- 1 avanderneut users 7781043 Oct 25 15:21 test.mp3
Run Code Online (Sandbox Code Playgroud)
并更改新文件:
/data0$ id3v2 -c "another file change" id3update/abc.mp3
/data0$ grep -F change mp3org/* id3update/*
Binary file id3update/abc.mp3 matches
Binary file id3update/test.mp3 matches
Run Code Online (Sandbox Code Playgroud)
如果mp3org
自动填充,您可以id3update
通过定期运行脚本来保持最新状态,该脚本执行cp --reflink src dst
如果目标尚不存在的情况。
¹最常出现在文件的开头