非常に大きな.csvファイル(> 500mb)があり、コマンドプロンプトでこれを小さな.csvファイルに分割したいと思います。 (基本的に、WindowsでLinuxの「分割」機能を見つけようとしています」。
私のマシンにはウィンドウしかインストールされておらず、ソフトウェアを要求するのは苦痛なので、これはバッチスクリプトでなければなりません。私はいくつかのサンプルコードに出会いました( http://forums.techguy.org/software-development/1023949-split-100000-line-csv-into.html )、しかし、バッチを実行すると動作します。私が取得するのは、20,000行ごとに解析するように要求したときに125kbだけの1つの出力ファイルです。
誰かが同様の問題に遭遇したことはありますか?また、どのように問題を解決しましたか?
これを試してください:
@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!
変数を変更することだけです。それが役に立てば幸い。
それを行う無料のWindowsアプリ
http://www.addictivetips.com/windows-tips/csv-splitter-for-windows/
CgwinコマンドSPLITを使用します。サンプル
500行ごとにファイルを分割するには:
split -l 500 [filename.ext]
デフォルトでは、拡張子の後にファイル名にxa、xb、xc ...を追加します
番号が付いて正しい拡張子で終わるファイルを生成するには、次を使用します
split -l 1000 sourcefilename.ext destinationfilename -d --additional-suffix=.ext
-dまたは-lの位置は重要ではありませんが、
詳細:split --help
非常に大きなファイルを分割する場合、私が見つけた解決策は 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%
同様の解決策を探しているときにこの質問を見つけました。 @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
これにより、1 to 20000
のnewfile1.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