Подтвердить что ты не робот

Разделить текстовый файл на несколько текстовых файлов с помощью командной строки

У меня есть несколько текстовых файлов, содержащих около 100 000 строк, и я хочу разбить их на более мелкие текстовые файлы по 5000 строк.

Я использовал:

split -l 5000 filename.txt

Это создает файлы:

xaa
xab
aac
xad
xbe
aaf

файлы без расширений. Я просто хочу называть их чем-то вроде:

file01.txt
file02.txt
file03.txt
file04.txt

или если это невозможно, я просто хочу, чтобы у них было расширение ".txt".

4b9b3361

Ответ 1

@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

Здесь вы можете создать собственную серию окон, которая должна выполнить задачу.

Теперь я не буду говорить, что он будет быстрым (менее 2 минут для каждого выходного файла 5Kline) или что он будет невосприимчив к пакетным символьным сенсибитивам. Действительно зависит от характеристик ваших целевых данных.

Я использовал файл с именем 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 в строке переименования файлов. )

Ответ 2

Я знаю, что вопрос задан давно, но я удивлен, что никто не дал самый простой ответ unix:

split -l 5000 -d --additional-suffix=.txt $FileName file
  • -l 5000: разделить файл на файлы по 5000 строк каждый.
  • -d: числовой суффикс. Это заставит суффикс перейти от 00 до 99 по умолчанию вместо aa в zz.
  • --additional-suffix: позволяет указать суффикс, здесь расширение
  • $FileName: имя файла, который нужно разделить.
  • file: префикс для добавления к результирующим файлам.

Как обычно, ознакомьтесь с man split для более подробной информации.

Ответ 3

Вот пример в С# (это то, что я искал). Мне нужно было разделить 23 ГБ csv файл с примерно 175 миллионами строк, чтобы иметь возможность просматривать файлы. Я разделил его на файлы по миллиону строк. Этот код сделал это примерно через 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);

Ответ 4

Синтаксис выглядит так:

$ split [OPTION] [INPUT [PREFIX]] 

где префикс PREFIXaa, PREFIXab,...

Просто используйте правильный, и вы сделали или просто используете mv для переименования. я думаю  $ mv * *.txt должен работать, но сначала проверять его на меньших масштабах.

:)

Ответ 5

Возможно, вы можете сделать что-то подобное с помощью awk

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

В основном, он вычисляет имя выходного файла, беря номер записи (NR) и деля его на 5000, добавляя 1, беря целое число этого и нулевое дополнение к 2 местам.

По умолчанию awk печатает всю входную запись, если вы ничего не укажете. Таким образом, print > outfile записывает всю входную запись в выходной файл.

Поскольку вы работаете в Windows, вы не можете использовать одинарные кавычки, потому что это не нравится. Я думаю, вы должны поместить script в файл, а затем сообщить awk, чтобы использовать файл, примерно так:

awk -f script.awk yourfile

и script.awk будет содержать script следующим образом:

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

Или это может сработать, если вы это сделаете:

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

Ответ 6

Мои требования были немного разными. Я часто работаю с файлами с разделителями-запятыми и с разделителями табуляции ASCII, где одна строка является одной записью данных. И они действительно большие, поэтому мне нужно разбить их на управляемые части (сохраняя строку заголовка).

Итак, я вернулся к своему классическому методу VBScript и объединил небольшой .vbs script, который можно запустить на любом компьютере Windows (он автоматически запускается движком WScript.exe script в окне).

Преимущество этого метода заключается в том, что он использует текстовые потоки, поэтому базовые данные не загружаются в память (или, по крайней мере, не все одновременно). В результате это происходит исключительно быстро и на самом деле не нужно много памяти для запуска. Тестовый файл, который я только что разделил, используя этот script на моем i7, составлял около 1 ГБ в размере файла, имел около 12 миллионов строк теста и составлял 25 файлов частей (каждая из которых имела около 500 тыс. Строк каждая) - обработка заняла около 2 минут и он не переходил на 3 МБ памяти, используемой в любой точке.

Оговорка здесь заключается в том, что он полагается на текстовый файл с "строками" (что означает, что каждая запись разделена CRLF), поскольку объект Text Stream использует функцию "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())

Ответ 7

Эта программа командной строки Windows "Файл Splitter" работает красиво: https://github.com/dubasdey/File-Splitter

Он с открытым исходным кодом, прост, документирован, проверен и работает для меня.

Пример:

fsplit -split 50 mb mylargefile.txt

Ответ 8

вот один из С#, который не исчерпывает память при разбиении на большие куски! Мне нужно было разделить 95M файл на 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();

Ответ 9

Я создал простую программу для этого, и ваш вопрос помог мне завершить решение... Я добавил еще одну функцию и несколько конфигураций. Если вы хотите добавить конкретный символ/строку после каждых нескольких строк (настраиваемый). Пожалуйста, просмотрите заметки. Я добавил файлы кода: https://github.com/mohitsharma779/FileSplit