使用 split 和 wc 命令按指定行数切分文本文件

概述

我们有一个内有 981 行的 foo.txt 文件,需要将其按每 10 行一个拆分为 100 个文件,拆分后文件名为 foo_{序号}.txt。

操作步骤

首先,使用 wc 命令查看文件行数:

$ wc -l foo.txt
981

然后结合文件总行数(total,即 wc 命令的结果)和拆分行数(target)计算得到序号的最大值所需位数: 

 在本例中:

 最后,使用 split 命令拆分文件:

$ split -d -l 10 -a 2 --additional-suffix .txt foo.txt foo_

得到拆分后的文件 foo_00.txt、foo_01.txt … foo_99.txt

命令解析

wc

wc 命令的作用是统计并输出文件中字、词和句的数量。

wc [OPTION]... [FILE]...

选项和参数

FILE 参数:需要统计的文件 -l 选项:增加后将只输出句的数量,即行数。

split

split 命令的作用是将文件按一定规则拆分为子文件。

split [OPTION]... [INPUT [PREFIX]]

选项和参数

INPUT 参数:需要拆分的文件 PREFIX 参数:可选,拆分后文件的子文件前缀,不提供时子文件的文件名将直接是序号 -d 选项:使用数字作为序号,序号默认从0开始。不提供时使用字母作为序号,即 aaab … 与 --numeric-suffixes 基本等价,但可通过 --numeric-suffixes={} 指定起始序号(-d 不支持) -l 选项:后跟行数,即按指定行数进行拆分( split 命令亦支持按字节数、字符数和个数等其他方式拆分) -a 选项:序号最大长度,默认会从 2 开始(见下方 FAQ 中的说明) ,当序号长度不足时候会在左侧补 0 --additional-suffix 选项:拆分后子文件额外增加的后缀

完整命令

最终完整的命令如下:

split -d -l {行数} -a {序号最大长度} --additional-suffix {拆分后后缀} {待拆分文件} {拆分后前缀}

FAQ

多次执行 split 命令时得到的子文件会相互覆盖吗?

会的,当使用同样的拆分前后缀拆分文件时,相同序号的子文件会直接覆盖且没有提示,需要额外留意。

split 命令中不使用 -a 选项会怎样?

根据文档,在不使用 -a 选项时有以下默认的行为:

By default split will initially create files with two generated suffix characters, and will increase this width by two when the next most significant position reaches the last character. (‘yz’, ‘zaaa’, ‘zaab’, …).

当序号的倒数第二位到达最大值(字符 z 为或数字为 9)时,序号长度会自动扩充两位。 在本例中,若不使用 -a 选项,第 91 个文件起的序号会变成 90009001 … 9008,而不是预期的 90 ~ 98

split 命令中 -a 选项设置过小会发生什么?

当 -a 选项设置过小,或未提供 -a 选项并使用了 --numeric-suffixes={} 指定起始序号且最终序号超过了 99 时 split 命令的会发生异常,并提示:

split: output file suffixes exhausted

此时拆分停止,但已经拆分得到的文件不受影响

子文件文件名中的序号可以做到不加0前缀吗?

仅通过 wc 和 split 是无法在一个命令做到的,需要通过手动计算并通过执行多个命令来实现,即先拆分“个位数”文件,再拆分“两位数”文件...

参考:https://stackoverflow.com/questions/39260770/split-file-with-output-file-with-numeric-suffix-but-without-begin-zero

其他说明

macOS 使用说明

macOS 自带的不是 GNU 的 split 命令(macOS 是基于 BSD 的),不支持 -d 参数。 要在 macOS 下使用 GNU 的 split 命令则需要先安装 coreutils

brew install coreutils

再使用 gsplit 命令(加 g 前缀)调用 GNU 的split 命令 其他 GNU 命令亦是类似的使用方法

其他参数

wc 命令亦包含其他参数,可参考: https://www.gnu.org/software/coreutils/manual/html_node/wc-invocation.html

split 命令亦包含其他参数,可参考: https://www.gnu.org/software/coreutils/manual/html_node/split-invocation.html