资讯动态

Linux大文件切割与合并:split、cat到校验的完整实践指南

发布时间:2026/10/17 12:36:10 来源:尧图企业网站定制
1. 先想清楚大文件为什么要切以及要付出什么代价接到这个标题可能很多人第一反应是“Linux 下切割文件不就是 split合并不就是 cat 吗这也值得写一篇”说实话这两个命令确实简单但实际工作中“切割大文件”这件事远比敲一条命令复杂——切什么类型、按什么粒度切、切完怎么传输、合并完怎么校验每一环都能挖出不少坑。我最初碰这个需求是处理一批生产环境产生的超大日志。单份日志几十 GB用文本编辑器根本打不开想传给同事做分析U 盘和网盘都扛不住服务器之间的传输也经常中断。后来把文件切成几百 MB 一份分批发过去再合并问题就解决了。还有一次是数据库备份文件有十几个 GB平台上传有单文件大小限制同样是切分后逐个上传、在目标机器上合并校验。可以说只要你在 Linux 下跟“大文件”打过交道迟早都会用到这套操作。这篇文章适合三类读者一是刚接触 Linux、想在服务器上处理大文件的开发者和运维二是需要跨机器或跨平台传输大体积数据的工程师三是对文件完整性格外敏感希望每一步都可验证的严谨派。我会从最基础的 split 和 cat 用法开始讲到分片传输、内容切分、数据校验最后分享几个我实际踩过的坑。目标很简单让你的大文件处理过程可复现、可验证、不出事故。不过先说句实在话切割确实有成本。文件被拆成多片之后你就要额外管理“有哪些分片”“分片顺序是什么”“是否全部传输完整”这类元信息。很多事故恰恰是发生在合并阶段——顺序错了、少了一片、传输过程中被截断最后拼出来的文件损坏还不自知。所以这篇文章的重点不光是怎么切怎么合还有怎么确认切和合的结果是对的。2. split 命令核心参数与三种实战切法2.1 先记住 split 的基本骨架split 命令的基本用法是split [选项] [输入文件] [输出文件名前缀]如果不指定输出文件名前缀默认以x为前缀生成xaa、xab、xac这样的分片。这个默认后缀看着比较懵实际使用中几乎所有人都会自定义前缀比如split -b 500M big_file.tar.gz part_上述命令会把big_file.tar.gz按 500MB 大小切成多份生成part_aa、part_ab、part_ac……这里part_就是我指定的前缀。参数-b表示按字节大小切割是使用频率最高的选项。split 最常用的参数有这么几个参数作用适合场景-b按字节大小切割支持 K、M、G 等单位二进制文件、压缩包、数据库备份-l按行数切割日志文件、TSV/CSV 文本-d用数字后缀代替字母后缀00、01、02分片较多时可读性更好-a指定后缀长度默认是 2分片数量超过 26×26 时必须调大--additional-suffix给分片追加额外后缀名给分片加 .part 或 .bin 便于识别这里的单位换算同样遵循 Linux 惯例K是 1024 字节M是 1024² 字节G是 1024³ 字节。你可能会遇到写kB、MB的旧版本语义略有差别建议统一用小写的k、m、g或大写的K、M、G现在的主流版本都按 1024 计算。2.2 按字节大小切割最稳妥的二进制切法对二进制文件比如.tar.gz、.zip、.bin、数据库 dump 文件最常用的就是按字节大小切割split -b 200M -d -a 3 --additional-suffix.part backup.tar.gz backup_执行后你会看到这样的文件列表backup_000.part backup_001.part backup_002.part ...我解释一下这串参数背后的考虑。-b 200M是主逻辑每片 200MB-d -a 3让后缀变成三位数字从000开始而不是默认的aa、ab这样排序和识别更直观--additional-suffix.part是给每个分片加上.part扩展名避免文件类型识别混乱。以后看到backup_000.part一眼就知道它是备份文件的第一片。为什么按字节而不是按行数切二进制文件因为二进制文件没有“行”的概念按行切只会得到一堆无意义的数据块。而且对二进制文件来说切片的粒度只影响“切点落在哪里”不影响内容本身能否被正确拼接。你甚至不需要理解文件内部是什么格式只要按字节切合并时按顺序拼接结果就和原文件完全一致。2.3 按行数切割处理日志和文本的优雅方案如果处理的是日志、CSV、JSON Lines 这类文本数据按行切比按大小切优雅得多。因为按字节切可能把一个完整行从中间截断后续处理每行数据时会很麻烦。按行切能保证每行都是完整的split -l 100000 access.log access_上面的命令把access.log按每 10 万行切成一份得到access_aa、access_ab、access_ac……这种方案在处理文本导入、日志归档时特别实用。有人会问我能不能用-b直接切文本当然能前提是你只关心文件大小不关心行完整性。但如果你还要按“行”去 grep、统计或者写脚本逐行处理切在行中间就会把一条数据劈成两半轻则统计出错重则解析报错。所以我处理文本时除非是临时传输否则都优先-l而不是-b。还有一个容易被忽略的细节-l后面跟的是行数不是字节数。对同一天日志不同时间段行长度差异很大按行数切出来的分片大小可能相差不少。如果你既要行完整、又要控制单文件大小实际操作中常是先给出行数上限的粗略估算切完再检查最大分片必要时调整参数重新切。2.4 后缀编号与命名规则不只为好看更是为不出错默认的 split 后缀是两位字母aa到zz所以最多只能产生 26×26 676 个分片。如果每个分片是 100MB满打满算才 67GB 左右。一旦文件更大后缀就会从两位变成三位甚至四位不同分片的后缀长度可能不一致排序和识别都很别扭。所以我的建议是大文件分片数可能超过 100 片时直接用-d -a 3生成三位数字后缀分片数超过 900 时用-a 4生成四位数字后缀。这样文件名始终形如backup_000.part配合ls默认的字典序排序也井然有序。命名规则的另一个作用体现在合并阶段。很多教程直接让你用cat backup_* backup.tar.gz这时通配符展开的顺序依赖ls的排序。用数字后缀且位数固定比如000到099排序就是天然的 0、1、2……顺序。如果你用了字母后缀且分片数超过 676新生成的xaaa和已有的xaa在字典序上并不是相邻关系cat x*合并出来的文件就会乱序。这个问题我在后面第 5 节还会展开说。3. 合并顺序、完整性与一条命令的安全性3.1 cat 合并看着简单顺序错了就前功尽弃合并的标准动作是cat backup_000.part backup_001.part backup_002.part backup.tar.gz或者用通配符cat backup_*.part backup.tar.gz命令本身没难度难的是保证“顺序正确”。如果你用cat backup_*.partShell 会按文件名展开而文件名排序按字符逐个比较。backup_0.part、backup_00.part、backup_000.part这几个名字排序结果可能和你直觉不一样。所以我在设计命名规则时一直强调要么用固定位数的数字要么干脆在合并脚本里明确写出分片顺序。这里有一个更隐蔽的问题通配符展开的顺序受区域设置影响。服务器的LC_ALL或LANG环境变量不同字符排序结果可能有差异。同一批文件名在你本地 Mac 上展开是一个顺序到了 CentOS 服务器上可能是另一个顺序。解决方法是不要依赖 Shell 展开在脚本里显式读取分片列表并排序。ls backup_*.part | sort -V | xargs cat backup.tar.gzsort -V是按版本号排序能正确处理backup_1.part和backup_10.part的顺序关系。如果你的分片全是定长数字后缀sort就够用如果历史遗留文件后缀长度不一sort -V更稳。3.2 校验合并完不等于合并对这是整篇文章我最想强调的一点。文件切割、传输、合并这套流程里最常见的“成功假象”是命令执行完毕、文件也生成了、大小看起来也对但内容已经损坏。比如分片传输出错某个分片少了最后几个字节合并时 Shell 不会报错cat只管把每个文件读完拼到一起。最后出来的合并文件大小少于原始文件但你如果不校验根本不会发现。再比如某个分片被别的进程写坏了一部分大小不变但内容变了这时候连大小对不上的线索都没有。所以正确的合并流程必须包含校验环节。我通常这样做切割前先计算原始文件的校验值md5sum big_file.tar.gz original.md5切割、传输、合并完成后再计算合并文件的校验值md5sum restored.tar.gz对比两个校验值是否一致。也可以用更安全的 sha256sha256sum big_file.tar.gz original.sha256 sha256sum restored.tar.gz用diff直接比对原始文件和合并文件也可以但对超大文件来说diff需要完整读取两次文件性能上不如校验值方案。校验值方案最明显的优势是开销小一条命令就能完成。3.3 一个完整的分片传输与合并脚本分享一个我常用的脚本模板。假设原始文件是backup.tar.gz目标是把分片传到另一台服务器的/data/restore/目录下再合并# 在源机器上切割并计算校验和 split -b 200M -d -a 3 --additional-suffix.part backup.tar.gz backup_ md5sum backup.tar.gz backup.md5 # 传输分片用 rsync 或 scp 均可 rsync -avP backup_*.part backup.md5 userremote:/data/restore/ # 在目标机器上合并并校验 cd /data/restore cat backup_*.part backup_restored.tar.gz md5sum -c backup.md5md5sum -c backup.md5会读取backup.md5中记录的原始校验值再对backup_restored.tar.gz计算校验值并自动对比输出OK或FAILED。这里我刻意把合并文件名写成backup_restored.tar.gz而不是覆盖掉原始备份名避免和目标机器上的其他文件混在一起。确认没问题之后再决定是否改名。我自己的习惯是再加一步合并完成后随机抽几个分片做抽查用head和tail看看分片内容是否符合预期。这条是在文件内容可分读时做的比如日志和文本。如果是纯二进制压缩包校验值就够了。4. 进阶变种按内容切分、dd 定点切割、管道实时切分4.1 csplit不是按大小切而是按“遇到什么”切有些场景下你切文件不想按大小而是想按内容边界切。比如一份超大的 SQL 导出文件里面按表分别 dump或者一个微型小说集合每章之间有固定分隔符。此时split帮不上忙要用csplit。csplit 的典型用法是csplit -z -f chapter_ book.txt /^第.*章$/ {99}这条命令的意思是在book.txt里查找匹配正则^第.*章$的行每遇到一次就在这一行之前把文件切一刀。-f chapter_指定输出前缀-z表示省略空文件{99}表示最多执行 99 次切分。如果是按固定行数切也可以用csplit -n 3 -f part_ data.txt 100 200 300100 200 300是切分点的行号这样能精确地在第 100 行、第 200 行、第 300 行处下刀。csplit 的逻辑比 split 复杂但它解决了一个很实际的问题对内容敏感的文件切割点必须是内容边界而不是字节边界。像前面提到的 SQL dump如果用split -b切可能在一行 INSERT 语句中间切断恢复时只能整体合并用没法单独拿一片导入调试。用 csplit 按表切每一片都是独立可用的文件。4.2 dd 定点切割低层控制与磁盘镜像场景如果需要对二进制文件做“从偏移量 X 开始提取 N 个字节”这种精细操作dd是更合适的工具。比如从损坏的磁盘镜像里提取指定分区区域或者从大文件中截取某一段验证数据dd ifbig_file.bin ofpart1.bin bs1M count100 skip0 statusprogress dd ifbig_file.bin ofpart2.bin bs1M count100 skip100 statusprogressskip100表示跳过前 100 个块每块大小由bs决定count100表示读取 100 块。这样两次命令就精确地取出了第 0~99 块和第 100~199 块。合并时还是可以用cat part1.bin part2.bin full.bin。dd 的最大优势是“精确”。它不像 split 那样自动连续切分而是完全由你指定每片从哪里开始、到哪里结束。DD 在磁盘恢复、取证分析、文件系统实验中几乎是标配。但要提醒一句bs的大小直接影响性能和精确度的平衡。bs1M适合多数情况如果切分点不在 1M 的整数倍上就要调整bs或者用skip、count配合精确字节数比如dd ifbig_file.bin ofmid.part bs1 count512 skip10485764.3 管道实时切分不落盘就把数据分开还有一种常见场景源文件本身不存在数据是从某个命令实时输出的。比如从压缩包流式读取并切分zcat big_log.gz | split -l 50000 - log_part_这里zcat解压后的数据直接喂给splitsplit 按每 5 万行生成一个分片分片前缀为log_part_。整个过程不需要在磁盘上保留一份完整解压后的文件既省空间又省 IO。类似地tar -cvf - /some/dir | split -b 100M - dir_backup_把目录打包后直接通过管道切分。管道切分有两个好处一是避免中间产物占磁盘二是天然适合流式数据处理管线。不过它也有代价——如果某个分片写坏了你没法重新生成这一个分片必须重新跑整个管道。所以重要的管道操作我通常配合tee把校验值也留一份。5. 我踩过的坑排序陷阱、后缀溢出与磁盘余量5.1 文件名排序陷阱not allcat *are equal这是个非常容易踩的坑特别是当分片数量超过 1000 时。假设你切了一个超大文件分片名为part_aa、part_ab……一直到part_zz之后出现part_aaa。此时执行cat part_*Shell 会先展开part_aa、part_ab、……part_zz然后才是part_aaa。问题来了part_aaa在字典序里排在part_aa之后还是之前答案是先比较前几个字符part_aa和part_aaa前五个字符都是part_aa但part_aa在这里已经结束part_aaa还有后续字符所以part_aaa会排在part_aa后面。粗看问题不大但如果你的字母后缀不是等长的某些part_ab和part_aba混在一起顺序就会乱。最稳妥的方案仍然是我前面说的用等长数字后缀。一旦用了-d -a 3文件名就是part_000到part_999sort或直接文件名展开都是天然正确的顺序。5.2 后缀长度耗尽不是文件太大是后缀不够用另一个让我印象深刻的教训是切分一个超过 6.7TB 的文件默认两位字母后缀split 直接报错因为后缀用完了。当时我以为命令写错实际上就是-a 2最多生成 676 个分片每片 10GB 就是 6.7TB。解决办法有两个一是加-a参数扩大后缀位数比如-a 4最多可以生成 26^4 456976 个分片二是用-d -a 3这种数字后缀数字能表示的范围更大。我后来统一用-d -a 3 --additional-suffix.part基本上不再操心后缀耗尽的问题。5.3 合并前必须看磁盘余量大到没朋友的文件这个坑很蠢但我还是踩过。有一次合并一个 50GB 的文件切分机器上临时目录只有 30GB 可用空间。cat写了一半直接报No space left on device而且不是原子操作——已经写入的部分会保留为一个残缺文件你得删掉重来。在处理好大文件时磁盘余量永远是第一道关卡。我的习惯是合并前先估算原始文件大小 * 至少留出 1.1 倍的空间还要考虑分片本身占用的空间。如果源分片和目标合并文件在同一目录那需要的空间就是原文件大小 分片大小总和。更保险的做法是合并到另一个挂载点并且在合并脚本开头写一个磁盘空间检查required$(du -sb backup_*.part | awk {s$1} END {print s}) available$(df --outputavail -B1 /data/restore | tail -1) if [ $required -gt $available ]; then echo 磁盘空间不足 exit 1 fi5.4 文本文件按字节切造成的中文乱码如果日志或文本里有中文按-b切分时切点可能落在某个汉字的 UTF-8 编码中间。这在单纯拼接回去时没问题但如果你单独查看某个分片或者对分片做 grep、awk 处理会遇到乱码和异常行。这个现象在我最初处理中文日志时吓了一跳以为文件损坏了。解决办法文本类文件优先用-l按行切。如果一定要按大小切并且后续还要单独处理每个分片那就切完做一次字符编码检查比如用file命令确认每个分片编码正常或者干脆先把文件转成按行的中间格式再切。对绝大多数业务场景按行切文本是最省心的。5.5 分片传输中的完整性传输工具本身不够很多人觉得用 rsync 传分片就万事大吉了确实 rsync 有自己的校验机制但它校验的是“传输过程是否一致”解决不了“源文件本身已经损坏”的问题。举例说明源机器上某个分片已经被写坏了一部分rsync 照样能把它完整传过去最后合并出来的文件同样是坏的。所以正确的流程一定是源端在切割后立刻生成校验值传完、合并完以后用校验值对比。把校验值这一步放在切割完、上传前做好而不是放在合并后。这样一旦发现问题还能判断是“切出来就是坏的”还是“传输出错了”。6. 我的日常习惯一套顺手的切割合并流程最后分享一套我实际用的工作流。它的优点是每一步都有验证适合处理重要数据缺点是命令略多但基本都是复制粘贴的程度。第一步切割前先建立工作目录mkdir -p split_work cd split_work第二步切割并生成校验值split -b 200M -d -a 3 --additional-suffix.part /path/to/backup.tar.gz backup_ md5sum /path/to/backup.tar.gz original.md5第三步传输分片。如果两台机器都有 rsync我用 rsync 并开启压缩rsync -avP backup_*.part original.md5 userremote:/data/restore/第四步目标机器上合并并校验cd /data/restore cat backup_*.part backup_restored.tar.gz md5sum -c original.md5第五步确认无误后再决定是否删除分片。注意只有在校验通过之后才删否则分片一删原始文件又不在本机那就真的回不去了。小文件、临时文件我不建议走这套流程直接scp或者rsync就够了。真正需要分片的是那些单个文件超过几 GB、传输中断概率高、或者目标系统有单文件大小限制的场景。这套流程我用了很久几乎没出过问题。还有一个体验上的小建议不要把分片大小设得太小。分片越多文件名管理和传输次数越多出错的概率反而越高。在平台允许的前提下100MB~1GB 的分片大小通常是比较舒适的范围既能抵抗传输中断又不会产生几百上千个文件。根据你自己的网络条件调一下不用教条。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑