使用命令行将文本文件拆分为较小的多个文本文件

ash*_*e97 67 cygwin command split batch-file text-files

我有多个文本文件,大约有100,000行,我想将它们分成每个5000行的较小文本文件.

我用了:

split -l 5000 filename.txt
Run Code Online (Sandbox Code Playgroud)

这会创建文件:

xaa
xab
aac
xad
xbe
aaf
Run Code Online (Sandbox Code Playgroud)

没有扩展名的文件.我只想打电话给他们:

file01.txt
file02.txt
file03.txt
file04.txt
Run Code Online (Sandbox Code Playgroud)

或者如果那是不可能的,我只希望它们具有".txt"扩展名.

urs*_*san 72

我知道很久以前就已经问过这个问题了,但我很惊讶没有人给出最简单的unix答案:

split -l 5000 -d --additional-suffix=.txt $FileName file
Run Code Online (Sandbox Code Playgroud)
  • -l 5000:将文件拆分为每行5,000行的文件.
  • -d:数字后缀.这将使后缀默认为00到99而不是aa到zz.
  • --additional-suffix:允许您指定后缀,此处为扩展名
  • $FileName:要拆分的文件的名称.
  • file:添加到结果文件的前缀.

一如既往,请man split查看更多详情.

对于Mac,默认版本split显然是愚蠢的.您可以使用以下命令安装GNU版本.(有关更多GNU工具,请参阅此问题)

brew install coreutils
Run Code Online (Sandbox Code Playgroud)

然后您可以通过更换运行上面的命令splitgsplit.查看man gsplit详细信息.

  • @StefanoMunarini for mac,您可以使用`brew install coreutils` 安装gnu 版本的split,然后在上面的命令中将`split` 替换为`gsplit`。 (3认同)
  • 如果我能+100,我会的!使用您发布的语法,我能够在大约.3秒的时间内将> 380M的文件拆分为10M的文件。 (2认同)
  • 似乎不再支持“-d”和“--additional-suffix”选项(OSX 10.12.6) (2认同)

Ale*_*lex 20

这是C#中的一个例子(因为这就是我要搜索的内容).我需要分割一个23 GB的csv文件,大约有1.75亿行,以便能够查看文件.我把它分成每个一百万行的文件.这段代码在我的机器上大约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);
Run Code Online (Sandbox Code Playgroud)

  • 而且,您基本上可以将其放入LINQPad中,并在两周内放心使用。无需编译任何东西。好的解决方案。 (2认同)

Mag*_*goo 15

@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
Run Code Online (Sandbox Code Playgroud)

这是一个应该完成任务的本机Windows批处理.

现在我不会说它会很快(每个5Kline输出文件不到2分钟)或者它不会对批量字符敏感性产生影响.真的取决于您的目标数据的特征.

我使用了一个名为q25249516.txt100Klines数据的文件进行测试.


修订更快的版本

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
Run Code Online (Sandbox Code Playgroud)

请注意,我使用llimit50000进行测试.将覆盖早期的文件编号,如果llimit*100比行的文件的数量gearter(固化通过设置fcount1999和使用~3代替~2的文件重命名线.)


Mar*_*ell 8

你也许可以做这样的事情 awk

awk '{outfile=sprintf("file%02d.txt",NR/5000+1);print > outfile}' yourfile
Run Code Online (Sandbox Code Playgroud)

基本上,它通过记录编号(NR)并将其除以5000来计算输出文件的名称,加1,将其整数和零填充取为2位.

默认情况下,awk在未指定任何其他内容时打印整个输入记录.因此,print > outfile将整个输入记录写入输出文件.

当您在Windows上运行时,您不能使用单引号,因为它不喜欢它.我认为你必须将脚本放在一个文件中,然后告诉awk使用该文件,如下所示:

awk -f script.awk yourfile
Run Code Online (Sandbox Code Playgroud)

并且script.awk将包含类似这样的脚本:

{outfile=sprintf("file%02d.txt",NR/5000+1);print > outfile}
Run Code Online (Sandbox Code Playgroud)

或者,如果您这样做可能会有效:

awk "{outfile=sprintf(\"file%02d.txt\",NR/5000+1);print > outfile}" yourfile
Run Code Online (Sandbox Code Playgroud)

  • 这使得第一个文件比其他文件少一行.正确的公式是`(NR-1)/ 5000 + 1` (2认同)

小智 7

语法如下:

$ split [OPTION] [INPUT [PREFIX]] 
Run Code Online (Sandbox Code Playgroud)

其中前缀是PREFIXaa,PREFIXab,...

只需使用正确的一个,你就完成了或只是使用mv进行重命名.我认为 $ mv * *.txt 应该工作,但首先在较小规模上测试它.

:)


小智 5

我的要求有点不同.我经常使用逗号分隔和制表符分隔的ASCII文件,其中单行是单个数据记录.而且它们非常大,所以我需要将它们分成可管理的部分(同时保留标题行).

因此,我恢复了我的经典VBScript方法,并将一个小的.vbs脚本混合在一起,该脚本可以在任何Windows计算机上运行(它由Window上的WScript.exe脚本主机引擎自动执行).

这种方法的好处是它使用Text Streams,因此底层数据不会加载到内存中(或者至少不会一次加载到内存中).结果是它非常快,并且它不需要太多内存来运行.我在i7上使用这个脚本分割的测试文件大约是1 GB的文件大小,有大约1200万行测试和25个部分文件(每个文件大约有500k行) - 处理大约需要2分钟而且没有任何时候都要使用超过3 MB的内存.

这里需要注意的是,它依赖于具有"行"的文本文件(意味着每个记录用CRLF分隔),因为文本流对象使用"ReadLine"函数一次处理一行.但是,嘿,如果你正在使用TSV或CSV文件,它是完美的.

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())
Run Code Online (Sandbox Code Playgroud)


Fab*_*ler 5

这个"File Splitter"Windows命令行程序运行良好:https://github.com/dubasdey/File-Splitter

它是开源的,简单的,记录的,经过验证的,并为我工作.

例:

fsplit -split 50 mb mylargefile.txt
Run Code Online (Sandbox Code Playgroud)