我有多个文本文件,每个文件大约有 100,000 行,我想将它们分割成每个文件 5,000 行的小型文本文件。
我使用了以下代码:
split -l 5000 filename.txt
那会创建文件:
xaa
xab
aac
xad
xbe
aaf
没有扩展名的文件。我只想给它们起一个类似于以下的名称:
file01.txt
file02.txt
file03.txt
file04.txt
如果不可能,我只想让它们有“.txt”扩展名。
我有多个文本文件,每个文件大约有 100,000 行,我想将它们分割成每个文件 5,000 行的小型文本文件。
我使用了以下代码:
split -l 5000 filename.txt
那会创建文件:
xaa
xab
aac
xad
xbe
aaf
没有扩展名的文件。我只想给它们起一个类似于以下的名称:
file01.txt
file02.txt
file03.txt
file04.txt
如果不可能,我只想让它们有“.txt”扩展名。
我知道这个问题很久以前就被问过了,但是我很惊讶没有人给出最直接的Unix答案:
split -l 5000 -d --additional-suffix=.txt $FileName file
-l 5000
: 将文件分割成每个文件包含 5,000 行的文件。-d
: 数字后缀。这将使后缀默认从 00 到 99,而不是从 aa 到 zz。--additional-suffix
: 允许您指定后缀,例如扩展名。$FileName
: 要拆分的文件的名称。file
: 添加到生成文件的前缀。像往常一样,查看 man split
获取更多详细信息。
对于Mac来说,默认版本的 split
比较简化。您可以使用以下命令安装 GNU 版本。(请参阅此问题以获取更多 GNU 工具)
brew install coreutils
然后,您可以通过将 split
替换为 gsplit
来执行上述命令。有关详细信息,请查看 man gsplit
。
brew install coreutils
安装GNU版本的split,并将上面的命令中的split
替换为gsplit
。 - ursansplit
命令。使用以下命令进入 Windows 目录:cd /mnt/c/
。 - Michał Stochmal这里有一个C#的例子(因为这就是我搜索的内容)。我需要将一个大约有1.75亿行的23GB csv文件进行分割以便于查看。我将其分成了每个文件一百万行。这段代码在我的电脑上用了约5分钟来完成:
var list = new List<string>();
var fileSuffix = 0;
using (var file = File.OpenRead(@"D:\Temp\file.csv"))
using (var reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
list.Add(reader.ReadLine());
if (list.Count >= 1000000)
{
File.WriteAllLines(@"D:\Temp\split" + (++fileSuffix) + ".csv", list);
list = new List<string>();
}
}
}
File.WriteAllLines(@"D:\Temp\split" + (++fileSuffix) + ".csv", list);
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET /a fcount=100
SET /a llimit=5000
SET /a lcount=%llimit%
FOR /f "usebackqdelims=" %%a IN ("%sourcedir%\q25249516.txt") DO (
CALL :select
FOR /f "tokens=1*delims==" %%b IN ('set dfile') DO IF /i "%%b"=="dfile" >>"%%c" ECHO(%%a
)
GOTO :EOF
:select
SET /a lcount+=1
IF %lcount% lss %llimit% GOTO :EOF
SET /a lcount=0
SET /a fcount+=1
SET "dfile=%sourcedir%\file%fcount:~-2%.txt"
GOTO :EOF
这里是一个本地的Windows批处理程序,应该可以完成任务。
我不会说它会很快(每个5K行输出文件少于2分钟),也不会说它能免疫批处理的字符敏感性。实际上,它取决于您的目标数据的特点。
我在测试中使用了一个名为q25249516.txt
的文件,其中包含100K行数据。
修订后的更快版本
REM
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET /a fcount=199
SET /a llimit=5000
SET /a lcount=%llimit%
FOR /f "usebackqdelims=" %%a IN ("%sourcedir%\q25249516.txt") DO (
CALL :select
>>"%sourcedir%\file$$.txt" ECHO(%%a
)
SET /a lcount=%llimit%
:select
SET /a lcount+=1
IF %lcount% lss %llimit% GOTO :EOF
SET /a lcount=0
SET /a fcount+=1
MOVE /y "%sourcedir%\file$$.txt" "%sourcedir%\file%fcount:~-2%.txt" >NUL 2>nul
GOTO :EOF
请注意,我在测试中使用了llimit
为50000。如果llimit
*100大于文件中的行数,则会覆盖早期的文件编号(通过将fcount
设置为1999
并在文件重命名行中使用~3
代替~2
来修复)。
fsplit -split 50 mb mylargefile.txt
你也许可以使用 awk
实现以下操作
awk '{outfile=sprintf("file%02d.txt",NR/5000+1);print > outfile}' yourfile
awk -f script.awk yourfile
而 script.awk
将包含以下脚本:
{outfile=sprintf("file%02d.txt",NR/5000+1);print > outfile}
awk "{outfile=sprintf(\"file%02d.txt\",NR/5000+1);print > outfile}" yourfile
(NR-1)/5000+1
。 - David Balažic语法看起来像:
$ split [OPTION] [INPUT [PREFIX]]
其中prefix是PREFIXaa、PREFIXab等,只需使用正确的前缀即可完成操作,或者使用mv进行重命名。我认为$ mv * *.txt
可以实现此功能,但请先在小范围内进行测试。
:)
Option Explicit
Private Const INPUT_TEXT_FILE = "c:\bigtextfile.txt" 'The full path to the big file
Private Const REPEAT_HEADER_ROW = True 'Set to True to duplicate the header row in each part file
Private Const LINES_PER_PART = 500000 'The number of lines per part file
Dim oFileSystem, oInputFile, oOutputFile, iOutputFile, iLineCounter, sHeaderLine, sLine, sFileExt, sStart
sStart = Now()
sFileExt = Right(INPUT_TEXT_FILE,Len(INPUT_TEXT_FILE)-InstrRev(INPUT_TEXT_FILE,".")+1)
iLineCounter = 0
iOutputFile = 1
Set oFileSystem = CreateObject("Scripting.FileSystemObject")
Set oInputFile = oFileSystem.OpenTextFile(INPUT_TEXT_FILE, 1, False)
Set oOutputFile = oFileSystem.OpenTextFile(Replace(INPUT_TEXT_FILE, sFileExt, "_" & iOutputFile & sFileExt), 2, True)
If REPEAT_HEADER_ROW Then
iLineCounter = 1
sHeaderLine = oInputFile.ReadLine()
Call oOutputFile.WriteLine(sHeaderLine)
End If
Do While Not oInputFile.AtEndOfStream
sLine = oInputFile.ReadLine()
Call oOutputFile.WriteLine(sLine)
iLineCounter = iLineCounter + 1
If iLineCounter Mod LINES_PER_PART = 0 Then
iOutputFile = iOutputFile + 1
Call oOutputFile.Close()
Set oOutputFile = oFileSystem.OpenTextFile(Replace(INPUT_TEXT_FILE, sFileExt, "_" & iOutputFile & sFileExt), 2, True)
If REPEAT_HEADER_ROW Then
Call oOutputFile.WriteLine(sHeaderLine)
End If
End If
Loop
Call oInputFile.Close()
Call oOutputFile.Close()
Set oFileSystem = Nothing
Call MsgBox("Done" & vbCrLf & "Lines Processed:" & iLineCounter & vbCrLf & "Part Files: " & iOutputFile & vbCrLf & "Start Time: " & sStart & vbCrLf & "Finish Time: " & Now())
以下是一个使用C#编写的算法,可以将大文件分割成多个大小为10M的小文件,而且不会出现内存不足的情况。
var fileSuffix = 0;
int lines = 0;
Stream fstream = File.OpenWrite($"{filename}.{(++fileSuffix)}");
StreamWriter sw = new StreamWriter(fstream);
using (var file = File.OpenRead(filename))
using (var reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
sw.WriteLine(reader.ReadLine());
lines++;
if (lines >= 10000000)
{
sw.Close();
fstream.Close();
lines = 0;
fstream = File.OpenWrite($"{filename}.{(++fileSuffix)}");
sw = new StreamWriter(fstream);
}
}
}
sw.Close();
fstream.Close();
我为此创建了一个简单的程序,你的问题帮助我完成了解决方案... 我添加了一个特性和几个配置项。 如果您想在每几行后添加特定字符/字符串(可配置),请查看备注。 我已经添加了代码文件: https://github.com/mohitsharma779/FileSplit
import os
from tqdm import tqdm
# Directorul în care se află fișierele txt
directory = r"d:\2022_12_02"
# Funcție pentru împărțirea fișierelor în părți mai mici
def split_txt_files(file_path, max_size):
with open(file_path, 'rb') as file:
data = file.read()
# Verifică dacă fișierul este deja mai mic sau egal cu dimensiunea maximă dorită
if len(data) <= max_size:
return [data]
parts = []
current_part = b''
for byte in data:
if len(current_part) + 1 > max_size:
parts.append(current_part)
current_part = b''
current_part += bytes([byte])
if current_part:
parts.append(current_part)
return parts
# Ittrează prin fișierele txt din director
for filename in os.listdir(directory):
if filename.endswith(".txt"):
file_path = os.path.join(directory, filename)
parts = split_txt_files(file_path, 1024 * 1024) # 1 MB în bytes
# Configurăm tqdm pentru afișarea progresului
progress_bar = tqdm(total=len(parts), desc=f"Splitting {filename}", unit="part")
for i, part in enumerate(parts):
part_filename = f"{os.path.splitext(filename)[0]}_part{i+1}.txt"
part_path = os.path.join(directory, part_filename)
with open(part_path, 'wb') as part_file:
part_file.write(part)
# Actualizăm progresul
progress_bar.update(1)
progress_bar.set_postfix({"Current Part": i+1})
print(f"Fișierul {part_filename} a fost creat.")
# Terminăm bara de progres
progress_bar.close()
split
(一个Unix / Linux实用程序),但标记为Windows的batch-file
。 - Mark Setchell