rus*_*ush 45 filesystems files
有 5 个大文件(file1、file2、..file5),每个文件大约 10G,磁盘上剩余的可用空间极少,我需要将所有这些文件连接成一个。不需要保留原始文件,只保留最后一个。
通常的连接是cat按顺序进行的文件file2.. file5:
cat file2 >> file1 ; rm file2
Run Code Online (Sandbox Code Playgroud)
不幸的是,这种方式需要至少 10G 的可用空间,我没有。有没有办法在不实际复制文件的情况下连接文件,但以某种方式告诉文件系统 file1 不会在原始 file1 结束处结束并在 file2 开始处继续?
附:如果重要的话,文件系统是 ext4。
Hau*_*ing 21
AFAIK(不幸的是)不可能从一开始就截断文件(这对于标准工具可能是正确的,但对于系统调用级别,请参见此处)。但是增加了一些复杂性,您可以使用正常的截断(与稀疏文件一起):您可以写入目标文件的末尾,而无需写入其间的所有数据。
让我们首先假设两个文件都是 5GiB (5120 MiB),并且您希望一次移动 100 MiB。您执行一个循环,其中包括
将源文件截断一个块(释放磁盘空间)
for((i=5119;i>=0;i--)); do
dd if=sourcefile of=targetfile bs=1M skip="$i" seek="$i" count=1
dd if=/dev/zero of=sourcefile bs=1M count=0 seek="$i"
done
Run Code Online (Sandbox Code Playgroud)但是请先尝试使用较小的测试文件,请...
可能文件既不是相同的大小,也不是块大小的倍数。在这种情况下,偏移量的计算变得更加复杂。seek_bytes然后skip_bytes应该使用。
如果这是您想要的方式,但需要有关详细信息的帮助,请再次询问。
警告
根据dd块大小,生成的文件将是碎片化的噩梦。
Rob*_*Bos 18
如果您的程序无法处理多个文件,那么与其将文件合并到一个文件中,不如用命名管道模拟单个文件。
mkfifo /tmp/file
cat file* >/tmp/file &
blahblah /tmp/file
rm /tmp/file
Run Code Online (Sandbox Code Playgroud)
正如 Hauke 建议的那样,losetup/dmsetup 也可以工作。一个快速的实验;我创建了 'file1..file4' 并做了一些努力:
for i in file*;do losetup -f ~/$i;done
numchunks=3
for i in `seq 0 $numchunks`; do
sizeinsectors=$((`ls -l file$i | awk '{print $5}'`/512))
startsector=$(($i*$sizeinsectors))
echo "$startsector $sizeinsectors linear /dev/loop$i 0"
done | dmsetup create joined
Run Code Online (Sandbox Code Playgroud)
然后,/dev/dm-0 包含一个以您的文件为内容的虚拟块设备。
我没有很好地测试过这个。
另一个编辑:文件大小必须能被 512 整除,否则你会丢失一些数据。如果是,那么你很好。我看到他在下面也提到了这一点。
Cel*_*ada 10
您必须编写一些东西来复制最多与您拥有的可用空间量一样大的数据。它应该像这样工作:
file2(pread()在读取到正确位置之前通过查找使用)。file1.fcntl(F_FREESP)从 中释放空间file2。