如何就地分割文件(写入新文件时删除原始文件)

如何就地分割文件(写入新文件时删除原始文件)

我的文件系统已满,并且有几个非常大的文件需要清理split(以便其中一些可以存档tar,其他可以检查)。有没有办法split实现“就地”行为?例如,我需要split -4 file写出四个新文件,而不使用文件系统上的任何额外空间。

有没有办法做到这一点?

答案1

不可能准确地在原地完成这件事。

也许您可以使用这个答案中建议的解决方案: 就地提取 tar 存档

archive="archive.tar"
chunkprefix="chunk_"
# 1-Mb chunks :
chunksize=1048576

totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
    # Print current chunk number, so we know it is still running.
    echo -n "$currentchunk "
    offset=$((currentchunk*chunksize))
    # Copy end of $archive to new file
    tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
    # Chop end of $archive
    truncate -s $offset "$archive"
    currentchunk=$((currentchunk-1))
done

它的作用是将文件的一部分复制到另一个文件中,然后立即从原始文件中将其删除。

这样您只需要 1MB 的可用磁盘空间(假设您分成 1MB)。

编辑:如果您没有可用磁盘空间,但有足够的 RAM,您可能能够创建一个 ramdisk 并将每个块存储在那里,同时删除原始块。不过还没有测试过:

ramsize=4096
rammount=/ramdisk
archive="archive.tar"
chunkprefix="$rammount/chunk_"
# 1-Mb chunks :
chunksize=1048576

mkdir $rammount
mkfs -q /dev/ram1 $ramsize
mount /dev/ram1 $rammount

totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
    # Print current chunk number, so we know it is still running.
    echo -n "$currentchunk "
    offset=$((currentchunk*chunksize))
    # Copy end of $archive to new file
    tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
    # Chop end of $archive
    truncate -s $offset "$archive"
    # copy the chunk on disk
    cp "$chunkprefix$currentchunk" .
    currentchunk=$((currentchunk-1))
done

它与脚本完全相同,只是它首先创建并安装一个 4MB 的 ramdisk,并将每个块临时存储在那里,直到通过截断原始文件释放空间。

答案2

您可以尝试使用映射到内存的文件系统空间 (tmpfs) 作为新文件的交换空间,直到原始文件被删除,从而为您提供将新文件移回磁盘的空间。有时这是 /dev/shm,或者只是 /tmp 或 /var/tmp,具体取决于您的 Linux 发行版。mount 的输出可能会向您指示安装在 tmpfs 上的文件系统空间

例如,在我手边的一台服务器上,mount 显示以下内容:

tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)

df -h告诉我关于/dev/shm

tmpfs                 249M     0  249M   0% /dev/shm

注意:如果该空间过满,则会影响需要内存才能正常运行的其他进程,会导致交换到 HDD 上的交换空间,这会增加 CPU 上下文交换时间,因为当该进程获得 CPU 周期时,它必须将这些内容从交换中加载回内存。

答案3

我认为这是不可能的,因为一个文件需要一个或多个,因此如果您不想在块边界处分割,则需要移动文件的其余部分,以便它从块的开头开始。

不过,你可以使用dd文件的一部分-存档或检查。

相关内容