Shell 命令系列之 split 小技巧

问题

这段代码有什么问题?

1
split -b $SPLIT_SIZE "$file" "${file}_part_"

答:如果是一行行的记录,在按照字节切割的时候会出现断行

解决方案

我: 使用 shell split 切割文件 如何保证按照文件大小切割并且不断行?比如按照 100MB 文件大小

GPT: split 命令可以用来将文件分割成多个小文件。-b 参数可以用来指定每个小文件的大小。例如,如果你想将文件分割成每个100MB的小文件,可以使用以下命令:

1
split -b 100m file_name

这将创建一系列的文件,名字为 xaa, xab, xac 等等,每个文件的大小都接近100MB。

但是,这种方法可能会在某些行的中间切割文件,这可能会导致问题,因为被切割的行可能无法正确解析。

如果你希望在分割文件时保持完整的行,那么你可以使用 -C 参数。这个参数允许你指定每个输出文件的最大行数,但是 split 命令会保证每个输出文件不会在一行的中间结束。例如:

1
split -C 100m file_name

这将创建一系列的文件,每个文件的大小都接近但不超过100MB,并且每个文件都会在一个完整的行结束。但是,这个命令可能会导致每个输出文件的大小略微超过你指定的大小,因为它会包含最后一个完整的行,即使这会导致文件的大小超过你指定的大小。

注意:-C 参数可能在一些老版本的 split 中不可用。

我:详细解释下 -C 和 -b 的区别?

GPT: split 命令的 -b-C 参数都用于指定输出文件的大小,但是它们在处理文件的行尾时有所不同。

-b 参数指定了每个输出文件的字节大小。例如,split -b 100m file_name 将会把输入文件 file_name 分割成大小接近100MB的小文件。这个命令将在指定的字节位置处分割文件,不考虑这个位置是否在一行的中间。

另一方面,-C 参数也用于指定每个输出文件的字节大小,但是它会保证每个输出文件在一个完整的行结束。例如,split -C 100m file_name 将会把输入文件 file_name 分割成大小接近但不超过100MB的小文件,而且每个文件都会在一个完整的行结束。这意味着,如果一个文件的大小正好是100MB,但是最后一个字节恰好在一行的中间,那么 split 命令会将这整行包含在当前文件中,而不是将它分割到下一个文件中。这可能会导致输出文件的大小略微超过你指定的大小。

总的来说,如果你希望严格控制输出文件的大小,并且不关心文件是否在一行的中间被分割,那么你应该使用 -b 参数。如果你希望每个输出文件都在一个完整的行结束,那么你应该使用 -C 参数,但是这可能会导致输出文件的大小略微超过你指定的大小。

我:请给我一些测试代码测试这两个区别的实现

GPT: 好的,让我们创建一个包含多行文本的文件,然后使用 split 命令的 -b-C 参数来分割它。

首先,我们创建一个文本文件:

1
2
3
4
5
echo "This is line 1
This is line 2
This is line 3
This is line 4
This is line 5" > testfile.txt

然后,我们可以使用 -b 参数来分割这个文件。我们将每个输出文件的大小设置为15字节:

1
split -b 15 testfile.txt test_b_

如果你查看 test_b_aatest_b_ab 文件,你会看到它们被分割在了 “line 1” 和 “This is line 2” 之间,这是因为 “This is line 1\n” 正好是15字节。

现在,我们使用 -C 参数来分割同一个文件。我们还是将每个输出文件的大小设置为15字节:

1
split -C 15 testfile.txt test_C_

这次,如果你查看 test_C_aatest_C_ab 文件,你会看到它们被分割在了 “This is line 1” 和 “This is line 2” 之间,即使 “This is line 1\n” 超过了15字节。这是因为 -C 参数保证了每个输出文件都在一个完整的行结束。

请注意,这个例子是为了演示 -b-C 参数的行为,实际上在大多数情况下,你会使用更大的文件和更大的输出文件大小。

后记

经过测试 15 字节是测不出来的,要 25,同时如果设为 5 字节(少于每行的字节数)也是有问题的,可以试试