在Linux最常用的文件生成和切片工具是dd,它功能比较全面,但无法以行为单位提取文件数据,也无法直接将文件按大小或行数进行均分(除非借助循环)。另两款数据分割工具split和csplit能够比较轻松地实现这些需求。csplit是split的升级版。
在处理很大的文件时,一个非常高效的思路是将大文件切割成多个小文件片段,然后再通过多个进程/线程对各个小文件进行操作,最后合并总数居。就像sort命令,它在实现排序时,底层算法就涉及到了将一个大文件切割成多个临时小文件。
dd命令
从if指定的文件读取数据,写入到of指定的文件。使用bs指定读取和写入的块大小,使用count指定读取和写入的数据块数量,bs和count相乘就是文件总大小。可以指定skip忽略读取if指定文件的前多少个块,seek指定写入到of指定文件时忽略前多少个块。
[root@master nginx]# dd if=/dev/zero of=/tmp/abc.1 bs=1M count=20 [root@master nginx]# ls /tmp/abc.1 -lh -rw-r--r-- 1 root root 20M 11月 29 16:45 /tmp/abc.1
if是input file,of是output file;bs有c(1byte)、w(2bytes)、b(512bytes)、kB(1000bytes)、K(1024bytes)、MB(1000)、M(1024)和GB、G等几种单位。因此,不要随意在单位后加上字母B。
现有文件access.log.bak的大小271M,需要将其切分后还原,切分的第一个小文件大小为20M。
[root@master ~]# dd if=/root/access.log.bak of=/root/access.txt bs=1M count=20 记录了20+0 的读入 记录了20+0 的写出 20971520字节(21 MB)已复制,0.651758 秒,32.2 MB/秒 [root@master ~]# ls -lh access.txt -rw-r--r-- 1 root root 20M 11月 29 16:49 access.txt
生成第二个小文件,由于第二个小文件不知道具体大小,所以不指定count选项。由于第二个小文件要从第20M处开始切分,于是需要忽略access.log.bak的前20M。假设bs=1M,于是skip掉的数据块数量为20。
[root@master ~]# dd if=/root/access.log.bak of=/root/access1.txt bs=1M skip=20 记录了250+1 的读入 记录了250+1 的写出 263095966字节(263 MB)已复制,10.0785 秒,26.1 MB/秒 [root@master ~]# ls access1.txt -lh -rw-r--r-- 1 root root 251M 11月 29 16:54 access1.txt
split命令
split工具的功能是将文件切分为多个小文件。既然要生成多个小文件,必然要指定切分文件的单位,支持按行切分以及按文件大小切分,另外还需解决小文件命名的问题。例如,文件名前缀、后缀。如果未明确指定前缀,则默认的前缀为"x"。
以下是命令的语法说明:
split [OPTION]... [INPUT [PREFIX]] -a N:生成长度为N的后缀,默认N=2 -b N:每个小文件的N,即按文件大小切分文件。支持K,M,G,T(换算单位1024)或KB,MB,GB(换算单位1000)等,默认单位为字节 -l N:每个小文件中有N行,即按行切分文件 -d N:指定生成数值格式的后缀替代默认的字母后缀,数值从N开始,默认为0。例如两位长度的后缀01/02/03 --additional-suffix=string:为每个小文件追加额外的后缀,例如加上".log"。有些老版本不支持该选项,在CentOS 7.2上已支持。 -n CHUNKS:将文件按照指定的CHUNKS方式进行分割。CHUNKS的有效形式有(具体用法见后文):N、l/N、l/K/N、K/N、r/N、r/K/N --filter CMD:不再直接切割输出到文件,而是切割后作为管道的输入,通过管道将切割的数据传递给CMD执行。如果需要指定文件,则split自动使用$FILE变量。见后文示例 INPUT:指定待切分的输入文件,如要切分标准输入,则使用"-" PREFIX:指定小文件的前缀,如果未指定,则默认为"x"
基本用法