web-dev-qa-db-ja.com

.csvファイルを分割するバッチファイル

非常に大きな.csvファイル(> 500mb)があり、コマンドプロンプトでこれを小さな.csvファイルに分割したいと思います。 (基本的に、WindowsでLinuxの「分割」機能を見つけようとしています」。

私のマシンにはウィンドウしかインストールされておらず、ソフトウェアを要求するのは苦痛なので、これはバッチスクリプトでなければなりません。私はいくつかのサンプルコードに出会いました( http://forums.techguy.org/software-development/1023949-split-100000-line-csv-into.html )、しかし、バッチを実行すると動作します。私が取得するのは、20,000行ごとに解析するように要求したときに125kbだけの1つの出力ファイルです。

誰かが同様の問題に遭遇したことはありますか?また、どのように問題を解決しましたか?

29
SeekingAlpha

これを試してください:

@echo off
setLocal EnableDelayedExpansion

set limit=20000
set file=export.csv
set lineCounter=1
set filenameCounter=1

set name=
set extension=
for %%a in (%file%) do (
    set "name=%%~na"
    set "extension=%%~xa"
)

for /f "tokens=*" %%a in (%file%) do (
    set splitFile=!name!-part!filenameCounter!!extension!
    if !lineCounter! gtr !limit! (
        set /a filenameCounter=!filenameCounter! + 1
        set lineCounter=1
        echo Created !splitFile!.
    )
    echo %%a>> !splitFile!

    set /a lineCounter=!lineCounter! + 1
)

上記のコードに示すように、元のcsvファイルを20 000行の制限を持つ複数のcsvファイルに分割します。必要なのは、それに応じて!file!および!limit!変数を変更することだけです。それが役に立てば幸い。

37
Dale
38
Gonki

CgwinコマンドSPLITを使用します。サンプル

500行ごとにファイルを分割するには:

split -l 500 [filename.ext]

デフォルトでは、拡張子の後にファイル名にxa、xb、xc ...を追加します

番号が付いて正しい拡張子で終わるファイルを生成するには、次を使用します

split -l 1000 sourcefilename.ext destinationfilename -d --additional-suffix=.ext

-dまたは-lの位置は重要ではありませんが、

  • "-d"-numeric-suffixesと同じです
  • "-l"-linesと同じです

詳細:split --help

13
hhh

非常に大きなファイルを分割する場合、私が見つけた解決策は this からの適応で、PowerShellをバッチファイルに「埋め込み」します。 これは、私が試した他の多くのこととは対照的に、高速に動作します(ここに掲載されている他のオプションについては知りません)。

以下のmysplit.batの使用方法は

mysplit.bat <mysize> 'myfile'

注:このスクリプトは、最初の引数を分割サイズとして使用することを目的としていました。現在、100Mbでハードコーディングされています。これを修正するのは難しくないはずです。

注2:filnameは単一引用符で囲む必要があります。引用のための他の代替手段は明らかに機能しません。

注3:指定された行数ではなく、指定されたバイト数でファイルを分割します。私にとってはこれで十分でした。次のCR/LFまで、各チャンクの読み取りを完了するために、おそらくいくつかのコード行を追加できます。これは、処理時間を犠牲にすることなく、(一定数ではなく)行ごとに分割されます。

スクリプトmysplit.bat

@REM Using https://stackoverflow.com/questions/19335004/how-to-run-a-powershell-script-from-a-batch-file
@REM and https://stackoverflow.com/questions/1001776/how-can-i-split-a-text-file-using-powershell
@PowerShell  ^
    $upperBound = 100MB;  ^
    $rootName = %2;  ^
    $from = $rootName;  ^
    $fromFile = [io.file]::OpenRead($from);  ^
    $buff = new-object byte[] $upperBound;  ^
    $count = $idx = 0;  ^
    try {  ^
        do {  ^
            'Reading ' + $upperBound;  ^
            $count = $fromFile.Read($buff, 0, $buff.Length);  ^
            if ($count -gt 0) {  ^
                $to = '{0}.{1}' -f ($rootName, $idx);  ^
                $toFile = [io.file]::OpenWrite($to);  ^
                try {  ^
                    'Writing ' + $count + ' to ' + $to;  ^
                    $tofile.Write($buff, 0, $count);  ^
                } finally {  ^
                    $tofile.Close();  ^
                }  ^
            }  ^
            $idx ++;  ^
        } while ($count -gt 0);  ^
    }  ^
    finally {  ^
        $fromFile.Close();  ^
    }  ^
%End PowerShell%
3
sancho.s

同様の解決策を探しているときにこの質問を見つけました。 @Daleの回答を目的に合わせて修正しました。もう少し柔軟性があり、エラーをトラップするものが欲しかった。同じものを探している人のためにここに置いてもいいと思った。

@echo off
setLocal EnableDelayedExpansion
GOTO checkvars

:checkvars
    IF "%1"=="" GOTO syntaxerror
    IF NOT "%1"=="-f"  GOTO syntaxerror
    IF %2=="" GOTO syntaxerror
    IF NOT EXIST %2 GOTO nofile
    IF "%3"=="" GOTO syntaxerror
    IF NOT "%3"=="-n" GOTO syntaxerror
    IF "%4"==""  GOTO syntaxerror
    set param=%4
    echo %param%| findstr /xr "[1-9][0-9]* 0" >nul && (
        goto proceed
    ) || (
        echo %param% is NOT a valid number
        goto syntaxerror
    )

:proceed
    set limit=%4
    set file=%2
    set lineCounter=1+%limit%
    set filenameCounter=0

    set name=
    set extension=

    for %%a in (%file%) do (
        set "name=%%~na"
        set "extension=%%~xa"
    )

    for /f "usebackq tokens=*" %%a in (%file%) do (
        if !lineCounter! gtr !limit! (
            set splitFile=!name!_part!filenameCounter!!extension!
            set /a filenameCounter=!filenameCounter! + 1
            set lineCounter=1
            echo Created !splitFile!.
        )
        cls
        echo Adding Line !splitFile! - !lineCounter!
        echo %%a>> !splitFile!
        set /a lineCounter=!lineCounter! + 1
    )
    echo Done!
    goto end
:syntaxerror
    Echo Syntax: %0 -f Filename -n "Number Of Rows Per File"
    goto end
:nofile
    echo %2 does not exist
    goto end
:end
0
SuperMykEl

これにより、1 to 20000newfile1.csv行が表示されます
および行20001 to the endファイル内newfile2.csv

また、1行あたりの8K文字の制限を克服します。

これはfindrepl.batというヘルパーバッチファイルを使用します-- https://www.dropbox.com/s/rfdldmcb6vwi9xc/findrepl.bat

findrepl.batをバッチファイルと同じフォルダーまたはパスに配置します。

単純なバッチファイルよりも堅牢で、高速です。

findrepl /o:1:20000 <file.csv >newfile1.csv
findrepl /o:20001   <file.csv >newfile2.csv
0
foxidrive