分割文件后再次加入文件的最佳方法是什么?


73

如果我有一个大文件,需要将其拆分为100兆字节的块,我会做

split -b 100m myImage.iso

通常给我这样的东西

xaa
xab
xac
xad

为了让他们重新在一起,我一直在使用

cat x* > myImage.iso

似乎应该有一种比读取一组文件中每一行代码cat并将输出重定向到新文件更有效的方法。就像只打开两个文件,EOF从第一个文件中删除标记并连接它们的方式一样-无需浏览所有内容。

Windows / DOS具有二进制文件的复制命令。帮助中提到该命令旨在能够合并多个文件。可以使用以下语法:(/b用于二进制模式)

copy /b file1 + file2 + file3 outputfile

在Linux上,有没有比cat相似或更好的方法来联接大文件?

更新资料

看来这cat实际上是加入文件的正确方法和最佳方法。很高兴知道我一直在使用正确的命令:)谢谢大家的反馈。


22
旁注:最好不要使用cat x*,因为文件的顺序取决于您的区域设置。最好先键入cat x,而不是按Esc,然后再键入*-您将看到文件的扩展顺序并可以重新排列。
rozcietrzewiacz 2011年

16
相反,cat x*您可以考虑使用外壳支撑扩展,cat xa{a..g}将指定的序列扩展为cat xaa xab xac xad xae xaf xag
Peter.O 2011年

3
@rozcietrzewiacz-您能举一个例子说明我如何调整可能会中断的语言环境设置cat x*吗?新的语言环境设置是否也不会受影响,split因此,如果splitcat x*在同一系统上使用,它们将始终有效?
cwd

3
“打开两个文件,从第一个文件中删除EOF标记,然后将它们连接-无需遍历所有内容。” ...听起来好像您需要发明一个新的文件系统才能完成您想要的工作
JoelFan

6
@cwd:split.c在GNU Coreutils中,后缀是由固定的字符数组构成的:static char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz";。后缀将不受语言环境的影响。(但我认为任何理智的语言环境都不会对小写字母进行重新排序;甚至EBCDIC都保持其标准顺序。)
Keith Thompson

Answers:


50

那就是为了什么cat。因为它是最古老的GNU工具之一,所以我认为其他任何工具都不可能更快,更好地做到这一点。而且它不是管道,而是仅重定向输出。


cat x, then press Esc您提到的技巧很巧妙。.我一直在寻找类似的东西,谢谢...好的评论和好的答案
Peter.O 2011年

2
不客气:)另外,当您在命令行中拥有该文件列表时,可以使用Ctrl+W剪切一个单词然后Ctrl+Y将其粘贴的方法。
rozcietrzewiacz 2011年

猫的意思是“连接”
JoelFan 2011年

4
..和从拉丁字“连锁”,这意味着“链”,“链状” derrives .. 串接是加入了链的链接。...(还有一些离题的话题,悬链曲线也源自“ catena”。这是链条悬挂的方式)
Peter.O 2011年

19

引擎盖下

没有比复制第一个文件然后在其后复制第二个文件等等更有效的方法了。DOS copycat这样做。

每个文件都独立于磁盘上的其他文件存储。几乎每个旨在将数据存储在类似磁盘的设备上的文件系统都是由块操作的。这是发生的情况的高度简化的表示形式:磁盘分为1kB的块,操作系统为每个文件存储组成它的块的列表。大多数文件的块长度不是整数,因此最后一个块仅被部分占用。实际上,文件系统具有许多优化,例如在几个文件之间共享最后的部分块,或者存储“块46798至47913”,而不是存储“块46798,块46799……”。当操作系统需要创建一个新文件时,它将寻找可用的块。块不必是连续的:如果只有4、5、98和178块可用,则仍可以存储4kB文件。

您可以在中间文件中支持部分块,但这会增加相当大的复杂性,尤其是在非顺序访问文件时:要跳到第10340个字节,您就不能再跳到第11个块的第100个字节,检查每个中间块的长度。

在使用块的情况下,您不能仅联接两个文件,因为通常第一个文件在块中间结束。当然,您可能会有特殊情况,但前提是您希望在连接时同时删除两个文件。对于罕见的操作,这将是非常具体的处理。这样的特殊处理不能靠自己生存,因为在典型的文件系统上,许多文件是同时访问的。因此,如果要添加优化,则需要仔细考虑:如果其他某个过程正在读取其中一个文件,会发生什么?如果有人在串联A和C的同时尝试串联A和B会发生什么?等等。总而言之,这种罕见的优化将是巨大的负担。

总而言之,如果不在其他地方做出重大牺牲,就无法提高连接文件的效率。这不值得。

关于拆分和合并

split并且cat是拆分和合并文件的简单方法。split负责产生按字母顺序命名的文件,因此cat *可用于连接。

cat加入的缺点是,它对于常见的故障模式不可靠。如果其中一个文件被截断或丢失,cat则不会抱怨,您只会得到损坏的输出。

有些压缩实用程序可以生成多部分存档,例如zipsplitrar -v。它们不是很统一,因为它们除了拆分外还压缩和打包(将多个文件组合成一个文件)(相反,除了连接外还要解压缩和解压缩)。但是它们很有用,因为它们可以验证您是否具有所有零件,以及零件是否完整。


8

似乎应该有比通过系统的stdin/ 管道传输所有内容更有效的方法stdout

除了那不是真的发生什么。Shell将stdout的stdout cat 直接连接到打开的文件,这意味着“通过stdout”与写入磁盘相同。


我只是在想象使用cat在控制台中显示几GB的代码,然后将其捕获并放入文件中。这就是我对使用cat并重定向看不见的输出时必须发生的事情的心理印象。似乎,如果有一种方法,您可以打开两个文件,将它们连接起来,然后关闭它们,则这比使用遍历所有代码行要有效cat。感谢您让我知道直接连接。
cwd

@cwd可以设计一个文件系统,在其中可以以这种方式连接两个文件,但这会使文件系统的设计复杂化。您需要针对一项操作进行优化,但代价是使许多常见任务变得更加复杂和缓慢。
吉尔斯

@Gilles-了解有关底层细节的更多信息会很有趣。对我来说,从硬盘上读取所有扇区以获得几个文件,然后将它们转储回磁盘上其他未使用的扇区,似乎效率很低。我认为大文件有时必须存储在多个空闲扇区块中,因为可能并不总是有足够的块并排存储它们。因此,从理论上讲,您可以通过删除EOF标记并在下一个文件的开头指向一组扇区来将文件合并为一个文件。* nix功能强大,所以我想知道是否有比猫更好的方法。
cwd

@cwd没有“ EOF标记”。没有一个理智的现代文件系统能像这样工作,因为它可以防止某些字符出现在文件中(否则需要复杂的编码)。但是,即使在大多数情况下,即使有一个EOF标记,您之后也都找不到正确的文件。
吉尔斯

我的意思是EOF标记的概念,而不是实际的EOF标记。否则,如果您查看硬盘驱动器上文件的位和字节,您如何知道文件的结尾?您是否在文件的开头指定了文件的长度?我说的是一个非常低级的东西。这就是您所说的吗?
cwd

3

我曾经遇到过这个问题:我想加入一些文件,但是没有足够的磁盘空间来容纳它们。

所以我写了一堆程序:

  • 通过读取文件,将其“发送”到stdout,如果完成,则将其删除以“吸收”文件
  • 还有一个可以“动态”缓存数据。

这使我能够做类似的事情

partto sourcefile | mybuffer 128M >>cumufile

因此在仍未写入128M的情况下删除了源文件。有点危险,但是如果数据不是那么珍贵,或者它们也存在于其他地方,那是可行的。

如果需要,我可以提供源。


0

从技术上讲,这是一种无需读取和写入整个内容即可访问整个文件的方法,对于大文件或空间不足的情况可能有用:

$ mkfifo myImage.iso
$ cat xa{a..g} > myImage.iso &

然后使用myImage.iso,例如

$ md5sum myImage.iso

尽管当然myImage.iso是一个特殊文件(命名管道),而不是常规文件,所以根据您要执行的操作,此文件是否有用。


0

文件分割

按大小分割

如果要将大文件拆分为小文件并选择小输出文件的名称和大小,则可以采用这种方法。

split -b 500M videos\BigVideoFile.avi SmallFile.

这样,您可以选择将一个大文件拆分为500 MB的较小部分。您还希望零件文件的名称是SmallFile。请注意,文件名后需要点。结果应该是生成新文件,如下所示:

SmallFile.ab SmallFile.ad SmallFile.af SmallFile.ah SmallFile.aj
SmallFile.aa SmallFile.ac SmallFile.ae SmallFile.ag SmallFile.ai SmallFile.ak
...

按行数拆分

通过这种方式,您可以将文本文件分割成较小的文件,每行限制为50行。

split -l 50 text_to_split.txt

结果应该是这样的:

xaa xab xac ...

按字节分割

分割成小文件,小文件的自定义大小以字节为单位:

split -b 2048 BigFile.mp4

结果应类似于按行数拆分的结果。

文件加入

您可以通过两种方式加入文件。第一个是:

cat SmallFile.* > OutputBigVideoFile.avi

或搭配:

cat SmallFile.?? > OutputBigVideoFile.avi

注意:加入文件时,小文件不应损坏。同样,所有小文件(部分)也应位于同一目录中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.