如何将一个文本文件分割成多个 .txt 文件?

81

我拥有一个文本文件 file.txt(12 MB),其中包含:

something1
something2
something3
something4
(...)

有没有办法将file.txt文件分成12个*.txt文件,比如file2.txtfile3.txtfile4.txt等?


10个回答

89

您可以使用 Linux Bash 核心实用程序 split

split -b 1M -d  file.txt file
注意,MMB都可以,但大小不同。MB是1000 * 1000,M是1024^2。 如果您想按行分隔,可以使用-l参数。 更新
a=(`wc -l yourfile`) ; lines=`echo $(($a/12)) | bc -l` ; split -l $lines -d  file.txt file

另一种解决方法是由Kirill提出的,您可以尝试以下内容:

split -n l/12 file.txt

注意这里是使用 l 而非 onesplit -n 有几个选项可以使用,例如 Nk/Nl/k/Nr/Nr/k/N


请问您能否更新一下如何通过使用split而不拆分行来确保文件数量是偶数的方法? - konsolebox
你可以使用 wc -l 命令获取文件总行数,然后运行以下命令来将文件拆分成多个小文件:a=(wc -l 你的文件) ; lines=echo $a/12 | bc -l ; split -l=$lines -d 你的文件.txt 文件 - CS Pei
有了所有这些复杂性,你本可以使用awk。但是这不适用于非文件输入,因为它不允许读取数据两次。只是说你之前声称的split可以做到这一点并不正确。而且正如预期的那样,你使用了wc - konsolebox
1
不错的更新,个人很高兴你没有使用awk来计算行数,因为可以在不完全读取文件的情况下实现。 按照这个逻辑,您还可以使用以下命令进行均等分割:a=(\wc -c yourfile`) ; n=12; bytes=`echo (a-a%n)/n` | bc -l` ; split -b=$bytes -d file.txt file`,如果您不使用可被整除的数字,则最后一个文件将包含剩余的字节。您的方法的派生似乎非常容易调整! - That Realty Programmer Guy
6
可以使用命令 split -n l/12 file.txt 来将文件分成 12 份,每份按行数平均分割。 - Kirill
显示剩余2条评论

84
$ split -l 100 input_file output_file

-l 是每个文件中行数的数量。这将创建:

  • output_fileaa
  • output_fileab
  • output_fileac
  • output_filead
  • ....

它是如何选择 aa、ab、ac 等的? - T. Brian Jones
1
@T.BrianJones 这个问题已经被分割处理了。 - viru
1
个��而言,我更喜欢使用“-d”选项来使得split命令使用数字后缀。 - Dror S.
有没有办法知道创建了多少个文件?我不是指手动计数,我的意思是命令分割输出那个或者有一个命令行参数告诉它输出那个? - Silidrone
要查找行数,请执行 wc -l <文件名> - A. K.

33

CS Pei的回答不能像原帖要求一样生成.txt文件。请使用以下代码:

split -b=1M -d  file.txt file --additional-suffix=.txt

8
这很有帮助 "--additional-suffix=.txt" - ruoho ruotsi
这里没有叫“John”的人。它指的是什么答案? - Peter Mortensen
好问题。一定是 CS Pei 提出的。我会编辑。 - schoon
我不知道选项“-b=1M”适用于哪个操作系统。但在Ubuntu和Centos上,选项“-b=1M”会报错“split: =1M: invalid number of bytes”。正确的选项是“-b 1M”或“--bytes=1M”。短选项需要空格。 - zhenguoli

2

使用 Bash

readarray -t lines < file.txt
count=${#lines[@]}

for i in "${!lines[@]}"; do
    index=$(( (i * 12 - 1) / count + 1 ))
    echo "${lines[i]}" >> "file${index}.txt"
done

使用 AWK

awk '{
    a[NR] = $0
}
END {
    for (i = 1; i in a; ++i) {
        x = (i * 12 - 1) / NR + 1
        sub(/\..*$/, "", x)
        print a[i] > "file" x ".txt"
    }
}' file.txt

split 不同,这个函数确保行数最为均匀。

1
split 也可以做到这个。 - CS Pei
@JohnSmith 是的,确实没快速看到那个选项。 - konsolebox
@JohnSmith 我撤回之前的话。我们怎样确保行数是均匀的?当然不能使用 wc -l 进行计算,否则我们就可以直接使用 bash 或 awk 了。这也是我编写脚本而不考虑 split 的原因。 - konsolebox

1

不管之前的回答说了什么,在我的Ubuntu 16.04(Xenial Xerus)上,我必须执行以下操作:

split -b 10M -d  system.log system_split.log

请注意-b和值之间的空格

1
没有使用additional-suffix选项,这会创建system_split.log1system_split.log2等文件吗? - Damien Roche
是的,它会这样做。 - Nicolas D

1
我的搜索引导我来到了这里,所以我在这里发布它,也为其他人提供帮助:
如果要获取文件的所有内容,则使用 "split" 是正确的答案!但是,对于那些只想从文件中提取一部分作为样本的人,请使用 "head" 或 "tail":
# extract just the **first** 100000 lines of /var/log/syslog into 
# ~/syslog_sample.txt
head -n 100000 /var/log/syslog > ~/syslog_sample.txt

# extract just the **last** 100000 lines of /var/log/syslog into 
# ~/syslog_sample.txt
tail -n 100000 /var/log/syslog > ~/syslog_sample.txt

0
在我的Linux系统(Red Hat Enterprise 6.9)上,split命令没有-n--additional-suffix的命令行选项。

相反,我使用了这个:

split -d -l NUM_LINES really_big_file.txt split_files.txt.

-d 是为 split_files.txt. 文件名添加数字后缀,-l 指定每个文件的行数。

例如,假设我有这样一个非常大的文件:

$ ls -laF
total 1391952
drwxr-xr-x 2 user.name group         40 Sep 14 15:43 ./
drwxr-xr-x 3 user.name group       4096 Sep 14 15:39 ../
-rw-r--r-- 1 user.name group 1425352817 Sep 14 14:01 really_big_file.txt

这个文件有100,000行,我想把它分成最多30,000行的文件。这个命令将运行拆分并在输出文件模式split_files.txt.的末尾附加一个整数。

$ split -d -l 30000 really_big_file.txt split_files.txt.

生成的文件按照每个文件最多30,000行正确拆分。

$ ls -laF
total 2783904
drwxr-xr-x 2 user.name group        156 Sep 14 15:43 ./
drwxr-xr-x 3 user.name group       4096 Sep 14 15:39 ../
-rw-r--r-- 1 user.name group 1425352817 Sep 14 14:01 really_big_file.txt
-rw-r--r-- 1 user.name group  428604626 Sep 14 15:43 split_files.txt.00
-rw-r--r-- 1 user.name group  427152423 Sep 14 15:43 split_files.txt.01
-rw-r--r-- 1 user.name group  427141443 Sep 14 15:43 split_files.txt.02
-rw-r--r-- 1 user.name group  142454325 Sep 14 15:43 split_files.txt.03


$ wc -l *.txt*
    100000 really_big_file.txt
     30000 split_files.txt.00
     30000 split_files.txt.01
     30000 split_files.txt.02
     10000 split_files.txt.03
    200000 total

0
如果每个部分具有相同数量的行,例如22行,这是我的解决方案:
split --numeric-suffixes=2 --additional-suffix=.txt -l 22 file.txt file

你可以获得 file2.txt 的前22行,file3.txt 的接下来的22行,以此类推。

感谢 @hamruta-takawale、@dror-s 和 @stackoverflowuser2010。


0

我同意@CS Pei的观点,但这对我没有用:

split -b=1M -d file.txt file

...因为-b后面的=使它失效了。相反,我只是删除了它,并且在变量和它之间没有留下空格,并使用小写字母"m":

split -b1m -d file.txt file

要附加“.txt”,我们使用@schoon所说的:

split -b=1m -d file.txt file --additional-suffix=.txt

我有一个188.5MB的txt文件,我使用了这个命令[但是用-b5m来分成5.2MB的文件],它返回了35个分割文件,所有这些文件都是txt文件,大小都是5.2MB,除了最后一个文件是5.0MB。现在,由于我希望我的行保持完整,我想将主文件每100万行拆分一次,但是split命令甚至不允许我做-100000,更不用说"-1000000"了,因此无法拆分大量行。


你只需要使用split命令的-C选项。 - Amit Naidu

0
尝试类似这样的代码:
awk -vc=1 'NR%1000000==0{++c}{print $0 > c".txt"}' Datafile.txt

for filename in *.txt; do mv "$filename" "Prefix_$filename"; done;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接