如何就地压缩文件?

如何就地压缩文件?

我有一台硬盘使用率为 90% 的机器。我想将其 500 多个日志文件压缩为一个较小的新文件。然而,硬盘太小,无法同时保存原始文件和压缩文件。

所以我需要的是将所有日志文件逐个压缩到一个新文件中,并在压缩后删除每个原始文件。

我怎样才能在 Linux 中做到这一点?

答案1

我自己想出了一个 tar 解决方案。
它将单个文件压缩到目标文件后删除。
不过,压缩速度不是很快。该命令如下所示:

tar -zcvf my_log.tar.gz *.log --remove-files

答案2

gzip或者bzip2将压缩文件并自动删除未压缩的文件(这是它们的默认行为)。

但是,请记住,在压缩过程中,两个文件都将存在。

如果您想压缩日志文件(即:包含文本的文件),您可能更喜欢bzip2,因为它对于文本文件具有更好的比率。

bzip2 -9 myfile       # will produce myfile.bz2

比较与示例:

$ ls -l myfile
-rw-rw-r-- 1 apaul apaul 585999 29 april 10:09 myfile

$ bzip2 -9 myfile

$ ls -l myfile*
-rw-rw-r-- 1 apaul apaul 115780 29 april 10:09 myfile.bz2

$ bunzip2 myfile.bz2

$ gzip -9 myfile

$ ls -l myfile*
-rw-rw-r-- 1 apaul apaul 146234 29 april 10:09 myfile.gz

更新正如 @Jjoao 在评论中告诉我的,有趣的是,xz似乎在普通文件及其默认选项上有一个最佳比例:

$ xz -9 myfile

$ ls -l myfile*
-rw-rw-r-- 1 apaul apaul 109384 29 april 10:09 myfile.xz

有关更多信息,这里是不同工具的有趣基准:http://binfalse.de/2011/04/04/comparison-of-compression/

对于上面的示例,我使用-9最佳压缩比,但如果压缩数据所需的时间比压缩比更重要,则最好不要使用它(使用较低的选项,即-1,或介于两者之间的选项)。

答案3

当您在 bash 中使用 io 重定向时>,在写入新数据之前原始文件将为空。

有一个命令 dd 可以覆盖文件的某些内容,而不是在写入之前清空文件,因此以下命令可能有效:

gzip -c some-file | dd conv=notrunc of=some-file

大多数情况下,压缩数据比原始数据小。当gzip读取前N个字节时,它只输出M个字节,其中M < N,因此可以安全地用压缩数据覆盖原始文件的前M个字节,并保留前N个字节后的数据不变。

但gzip结束后会有数据。

但是,如果 dd 写入速度比 gzip 快,我不知道会发生什么。


或者你可以通过losetup将文件映射到块设备。对于块设备,写操作不会清空原始数据。

loop_device=$(losetup -f--show some-file)
gzip -c $loop_device > $loop_device

答案4

我试图在 BSD 版本的 tar 上执行此操作。在这种情况下,--remove-files 选项不可用。我最终做的(和工作的)是:

find folder_to_tar -type f -exec tar --append --file=output_tar_file.tar {} \; -exec rm -v {} \;

相关内容