split 命令详解与参数实测(Ubuntu 22.04)
GNU split 参数实测:-l/-n/-b 三种切分、-d/-a/--additional-suffix 命名、-e 空片与 md5 合并还原校验,Ubuntu 22.04(coreutils 8.32)全部命令回显实测。
split 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 GNU split 的每一个参数——默认 1000 行切分与 xaa 命名、
-l按行、-n均分、-b按字节(1K/1M)、-d数字后缀、-a后缀长度、--additional-suffix追加扩展名、-e不生成空文件,以及切分后合并还原的 md5 校验闭环,全部命令与回显已在 Ubuntu 22.04(GNU coreutils 8.32)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- split 版本:GNU coreutils 8.32(
split --version实测) - split 属于 coreutils 基础工具集,Ubuntu 22.04 默认预装,无需额外安装
- 演示目录:
/root/demo/split/ - 测试数据:
num.txt(12 行、96 字节的编号行文本);实战部分临时生成约 50 KiB 与 2.5 MiB 的二进制流文件
二、命令概览
2.1 语法与测试数据准备
split 的语法是 split [OPTION]... [FILE [PREFIX]]:把 FILE 切成若干个小文件,命名为 PREFIXaa、PREFIXab(或数字后缀 PREFIX00),不指定 PREFIX 时默认前缀为 x;不指定 FILE 时读标准输入。切分维度有三种:按行数(-l,默认 1000 行)、按字节(-b)、按份数(-n)。
先生成一套 12 行的演示数据(seq -f 按格式生成 line 01 到 line 12),后续所有参数实测都基于它:
mkdir -p /root/demo/split
seq -f "line %02g" 1 12 > /root/demo/split/num.txt
进入演示目录并确认数据就绪:
$ cd /root/demo/split
$ cat num.txt
line 01
line 02
line 03
line 04
line 05
line 06
line 07
line 08
line 09
line 10
line 11
line 12
$ wc -l num.txt
12 num.txt
每行 8 字节、共 12 行 96 字节,行数与字节数都足够小,便于观察每条切分命令的完整产物。
2.2 --help 全量回显
split --help 输出全部参数清单(实测原样保留,可作为参数速查):
Usage: split [OPTION]... [FILE [PREFIX]]
Output pieces of FILE to PREFIXaa, PREFIXab, ...;
default size is 1000 lines, and default PREFIX is 'x'.
With no FILE, or when FILE is -, read standard input.
Mandatory arguments to long options are mandatory for short options too.
-a, --suffix-length=N generate suffixes of length N (default 2)
--additional-suffix=SUFFIX append an additional SUFFIX to file names
-b, --bytes=SIZE put SIZE bytes per output file
-C, --line-bytes=SIZE put at most SIZE bytes of records per output file
-d use numeric suffixes starting at 0, not alphabetic
--numeric-suffixes[=FROM] same as -d, but allow setting the start value
-x use hex suffixes starting at 0, not alphabetic
--hex-suffixes[=FROM] same as -x, but allow setting the start value
-e, --elide-empty-files do not generate empty output files with '-n'
--filter=COMMAND write to shell COMMAND; file name is $FILE
-l, --lines=NUMBER put NUMBER lines/records per output file
-n, --number=CHUNKS generate CHUNKS output files; see explanation below
-t, --separator=SEP use SEP instead of newline as the record separator;
'\0' (zero) specifies the NUL character
-u, --unbuffered immediately copy input to output with '-n r/...'
--verbose print a diagnostic just before each
output file is opened
--help display this help and exit
--version output version information and exit
The SIZE argument is an integer and optional unit (example: 10K is 10*1024).
Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers of 1000).
Binary prefixes can be used, too: KiB=K, MiB=M, and so on.
CHUNKS may be:
N split into N files based on size of input
K/N output Kth of N to stdout
l/N split into N files without splitting lines/records
l/K/N output Kth of N to stdout without splitting lines/records
r/N like 'l' but use round robin distribution
r/K/N likewise but only output Kth of N to stdout
GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/split>
or available locally via: info '(coreutils) split invocation'
💡 说明:帮助明示两个默认值——切分大小默认 1000 行、文件名前缀默认
x(后缀两位字母)。SIZE 单位K/M/G按 1024 进制、KB/MB按 1000 进制(KiB=K等二进制前缀别名同样可用);CHUNKS除整数 N 外还支持l/N(不切断行)等形态,见 4.2 与常见问题。
2.3 版本确认
$ split --version | head -1
split (GNU coreutils) 8.32
三、参数逐项实测
3.1 默认用法:每 1000 行一切,前缀 x
不带参数切分 12 行的文件——因为达不到默认的 1000 行阈值,只产出 1 个文件:
$ split num.txt
$ ls -l
total 8
-rw-r--r-- 1 root root 96 Oct 15 07:35 num.txt
-rw-r--r-- 1 root root 96 Oct 15 07:35 xaa
$ wc -l xaa
12 xaa
$ rm -f x*
命名规则一目了然:默认前缀 x + 两位字母后缀,第一片叫 xaa(够 1000 行时第二片叫 xab,依此类推)。12 行全部进了 xaa,内容与原文件一致。
💡 提示:
rm -f x*这类通配清理只删切分产物,前提是原文件名不以x开头。规划前缀(见 3.2 的part_)能从根上避免误删。
3.2 -l:按行数切分
-l NUMBER 指定每个切片的行数。12 行按每 4 行一切,得到 3 片:
$ split -l 4 num.txt part_
$ ls part_*
part_aa
part_ab
part_ac
$ wc -l part_aa part_ab part_ac
4 part_aa
4 part_ab
4 part_ac
12 total
$ rm -f part_*
自定义前缀 part_ + 默认两位字母后缀,产物为 part_aa、part_ab、part_ac,每片恰好 4 行,总数 12 行与原文件一致。
💡 提示:
-l是最贴近"记录型文本"的切法,不会把一行切成两半;按字节切(-b/-n)就可能切在行中间,见 3.3。
3.3 -n:均分为 N 份
-n CHUNKS 把输入均分成 N 份(按字节均分,每份大小相等):
$ wc -c num.txt
96 num.txt
$ split -n 3 num.txt eq_
$ ls eq_*
eq_aa
eq_ab
eq_ac
$ wc -c eq_aa eq_ab eq_ac
32 eq_aa
32 eq_ab
32 eq_ac
96 total
$ cat eq_aa
line 01
line 02
line 03
line 04
$ rm -f eq_*
96 字节 ÷ 3 = 每片 32 字节,恰好是 4 行的长度,所以本例每片边界正好落在行尾。若字节数不能被 N 整除,最后几片会短一些;若行宽不是每片字节数的整数倍,行会被从中间切开——这是 -n 与 -l 的本质区别。
💡 提示:帮助原文的 CHUNKS 形态里,
l/N表示"均分 N 份且不切断行/记录",K/N表示"只把第 K 片写到标准输出",按行不切分的需求优先用l/N。
3.4 -b:按字节切分(1K/1M)
-b SIZE 按字节大小切,SIZE 支持二进制单位(K=1024)。先生成 51200 字节(50 KiB)的流文件再按 20K 切:
$ yes '0123456789abcdef' | head -c 51200 > big.bin
$ ls -l big.bin
-rw-r--r-- 1 root root 51200 Oct 15 07:35 big.bin
$ split -b 20K big.bin chunk_
$ ls -l chunk_*
-rw-r--r-- 1 root root 20480 Oct 15 07:35 chunk_aa
-rw-r--r-- 1 root root 20480 Oct 15 07:35 chunk_ab
-rw-r--r-- 1 root root 10240 Oct 15 07:35 chunk_ac
$ rm -f chunk_*
前两片各 20480 字节(20 × 1024),最后一片 10240 字节装剩余部分——最后一片允许小于 SIZE。yes | head -c 是快速造指定大小测试文件的常用组合,1M 级别的演示见 4.1。
💡 技术拓展:SIZE 单位有两套进制,选错会有约 2.4% 的偏差——
写法 进制 换算 适用 K / M / G(=KiB/MiB/GiB) 1024 20K = 20480 字节 本地磁盘、dd/split 习惯 KB / MB / GB 1000 20KB = 20000 字节 网络传输、存储厂商标称 本文实测采用二进制
K(20K = 20480 字节,与ls -l回显吻合);对账类脚本务必显式写清单位写法。
3.5 -d:数字后缀
-d 把后缀从字母 aa/ab 换成从 0 起的数字 00/01:
$ split -l 4 -d num.txt npart_
$ ls npart_*
npart_00
npart_01
npart_02
$ rm -f npart_*
数字后缀在脚本里更好排序、更好拼循环变量。帮助原文显示 --numeric-suffixes[=FROM] 与 -d 等价但可另设起始值。
💡 提示:
-d常与-a(后缀位数)、--additional-suffix(扩展名)组合,见 3.6、3.7 与 4.2。
3.6 -a:指定后缀长度
-a N 把后缀长度从默认 2 位改为 N 位,扩大可编码的切片数量:
$ split -l 4 -a 3 num.txt long_
$ ls long_*
long_aaa
long_aab
long_aac
$ rm -f long_*
三位字母后缀从 aaa 起编。默认两位后缀最多表示 26² = 676 片,切片数可能超过它的大文件场景(如 -b 1M 切超大日志)需要加长后缀。
💡 提示:
-a与-d组合时后缀是 N 位数字(如-a 3 -d产出000);后缀位数不足以编号时会直接报错,此时必须加长-a。
3.7 --additional-suffix:追加扩展名
--additional-suffix=SUFFIX 在后缀之后再追加一段固定字符串,让切片直接带上扩展名:
$ split -l 4 -d --additional-suffix=.txt num.txt piece_
$ ls piece_*
piece_00.txt
piece_01.txt
piece_02.txt
$ rm -f piece_*
最终文件名 = 前缀 piece_ + 数字后缀 00 + 追加后缀 .txt。切片能直接被按扩展名识别的程序(编辑器、打包工具)处理。
💡 提示:追加后缀不影响合并还原——
cat piece_*.txt仍按字典序拼回原文,顺序与无扩展名时一致。
3.8 -e:不生成空文件
-e(--elide-empty-files)配合 -n 使用:数据不足以填满全部切片时,空切片不再落盘。用 4 字节的 tiny.txt 均分 6 份做对照,先不加 -e:
$ printf 'abc\n' > tiny.txt
$ wc -c tiny.txt
4 tiny.txt
$ split -n 6 tiny.txt
$ ls x*
xaa
xab
xac
xad
xae
xaf
$ wc -c x*
1 xaa
1 xab
1 xac
1 xad
0 xae
0 xaf
4 total
$ rm -f x*
6 片里前 4 片各 1 字节,后 2 片(xae、xaf)是 0 字节空文件。加 -e 再切一次:
$ split -e -n 6 tiny.txt
$ ls x*
xaa
xab
xac
xad
$ wc -c x*
1 xaa
1 xab
1 xac
1 xad
4 total
$ rm -f x* tiny.txt
两个空文件被省略,只剩 4 个非空切片。批量任务里空切片常会让下游 while read 空转或触发"文件不存在"误判,-e 是干净的解法。
💡 提示:帮助原文注明
-e的作用范围是-n切分;-l/-b切分天然不会产生空文件(数据耗尽即停止)。
四、实战示例
4.1 大文件按 1M 切块归档
生成 2621440 字节(2.5 MiB)的流文件,按 1M 切块——这是把超大日志搬进有单文件大小限制的传输通道前的典型预处理:
$ yes '0123456789' | head -c 2621440 > big2.bin
$ split -b 1M big2.bin m_
$ ls -l m_*
-rw-r--r-- 1 root root 1048576 Oct 15 07:35 m_aa
-rw-r--r-- 1 root root 1048576 Oct 15 07:35 m_ab
-rw-r--r-- 1 root root 524288 Oct 15 07:35 m_ac
$ rm -f m_* big.bin big2.bin
1048576 字节 = 1 MiB,实测与 -b 1M 的二进制语义一致;m_ac 装剩余的 0.5 MiB。传输完成后按 4.3 合并校验即可。
4.2 均分数据集 + 数字后缀 + 自定义前缀
把数据集均分成 3 份做并行处理,-d -n 3 组合直接得到规整的编号文件:
$ split -d -n 3 num.txt eqn_
$ ls eqn_*
eqn_00
eqn_01
eqn_02
$ cat eqn_00
line 01
line 02
line 03
line 04
$ rm -f eqn_*
eqn_00、eqn_01、eqn_02 每份 32 字节(4 行),可直接喂给 3 个并行任务。
4.3 切分后合并还原与 md5 校验
split 出的切片用 cat 按字典序合并即可还原,md5sum 双值对比是完整性验收的标准动作:
$ split -l 4 num.txt
$ ls x*
xaa
xab
xac
$ cat xa* > restored.txt
$ md5sum num.txt restored.txt
75a832be30dbc08ad7449a9ca42cbbca num.txt
75a832be30dbc08ad7449a9ca42cbbca restored.txt
$ diff num.txt restored.txt && echo identical
identical
$ rm -f x* restored.txt
两个 md5 值完全一致(75a832be30dbc08ad7449a9ca42cbbca),diff 无差异——合并还原零丢失。关键在 xa* 的展开顺序:shell 按字典序展开 xaa xab xac,与切分顺序一致,因此拼接顺序天然正确。
五、注意事项与常见问题
Q1:默认切分为什么只得到一个 xaa?
默认每 1000 行切一片(帮助原文:default size is 1000 lines),12 行的小文件不够一片。想看到多片要么加 -l/-b/-n,要么文件真的超过 1000 行(见 3.1)。
Q2:合并还原时顺序错乱怎么办?
cat x* 依赖 shell 字典序展开,xaa、xab、xac 天然有序;但 -d 数字后缀在超过 10 片且后缀位数不一时(如 x9 与 x10 混排)会乱序——保持后缀定长(默认 2 位或用 -a)即可,最终用 md5sum 双值校验兜底(见 4.3)。
Q3:-n 均分会把一行切成两半吗?
会。-n N 按字节均分,行边界不在切点上时就被切开(3.3 的例子恰好整除没切到)。不切行用帮助原文中的 l/N 形态,或改用 -l。
Q4:数字后缀从 00 还是从 01 开始?
从 00 开始(帮助原文:use numeric suffixes starting at 0)。需要从其他值起编用 --numeric-suffixes=FROM。
Q5:后缀不够用了怎么报错、怎么救?
默认两位后缀最多 676 片(字母)或 100 片(-d 数字),超出时 split 报"output file suffixes exhausted"类错误退出。预防性加长后缀:-a 3(见 3.6)。
Q6:切分产物能否不落盘、直接进管道?
可以。帮助原文提供 --filter=COMMAND:每个切片写由 COMMAND 处理(切片文件名通过 $FILE 传入),常用于"边切边压缩"场景;本文以落盘实测为主,该参数按帮助原文使用。
Q7:rm -f x* 会误删原文件吗?
只当原文件名匹配通配时才会。本文 num.txt 不以 x 开头所以安全;更稳妥的习惯是一开始就用带业务含义的前缀(part_、piece_),让"原文件"与"切片"在命名空间上隔离(见 3.2、3.7)。
Q8:split 与 csplit 怎么选? 按固定大小/行数切选 split;按内容模式(章节标题、错误标记)切选 csplit,详见《csplit 命令详解与参数实测(Ubuntu 22.04)》中的工具对比表。
六、参考链接
- GNU coreutils 官方手册(split 章节):https://www.gnu.org/software/coreutils/manual/html_node/split-invocation.html
- 在线文档:https://www.gnu.org/software/coreutils/split
- 本机帮助:
split --help、man split(Ubuntu 22.04 内置)