Powershellでファイルを分割する

Powershellでバイナリーファイルを分割したくなった。
検索すると、ReadAllBytesで読込んでしまうのが出てきたので、少し修正した。
ついでに、テキストの行数分割もつけたけど、、、遅いし、UTF-16で出力されることに注意。
属性と最終更新日付も保持するよ!(最初の分割ファイルに持たせる)



スクリプト

Split-Content (ファイル名)
でファイルのある場所に「.001」〜を付与して分割。
Join-Content (ファイル名。「.001」なしの)
で、分割ファイルのある場所に結合。
どちらも、「-Text」で行数分割ができる。
分割時のサイズは、初期1MB。変える場合は「-Size」パラメーターで。


分割後のサイズでバッファをとってるけど、それも小さくしたい場合は、さらに修正が必要。
もともとは小さいバッファでループするようにしてたけど、不要かと思って削った。
そのため、Split側の出力がFileStreamになってたりする。

function Split-Content() {
	Param(
		[string]$Path,
		[int]$ReadCount = 1000,
		[int]$Size = 1048576,
		[switch]$Text
	)

	$count = 1
	$src = New-Object System.IO.FileInfo($Path)
	if($src.Exists) {
		if($Text) {
			Get-Content $Path -ReadCount $ReadCount | ForEach-Object {
				$_ > ($Path + ('.{0:D3}' -f $count))
				$count++
			}
		} else {
			$srcLen = $src.Length
			$dstLen = 0
			$buf = New-Object byte[] $Size
			$srcFs = $src.OpenRead()
			while($dstLen -lt $srcLen) {
				$nowLen = $Size
				if($nowLen -gt $srcLen - $dstLen) { $nowLen = $srcLen - $dstLen }
				$nowLen = $srcFs.Read($buf, 0, $nowLen)
				$dstFs = New-Object System.IO.FileStream(($Path + ('.{0:D3}' -f $count)), 'Create')
				$dstFs.Write($buf, 0, $nowLen)
				$dstFs.Dispose()
				$count++
				$dstLen += $nowLen
			}
			$srcFs.Dispose()
		}
		$dst = New-Object System.IO.FileInfo($Path + '.001')
		$dst.LastWriteTime = $src.LastWriteTime
		$dst.Attributes = $src.Attributes
	}
}

function Join-Content() {
	Param(
		[string]$Path,
		[switch]$Text
	)

	if(Test-Path $Path) {
		$res = ''
		while($res -ne 'y' -and $res -ne 'n') {
			$res = Read-Host 'overwrite? (y/n)'
		}
		if($res -eq 'n') { return; }
		Remove-Item -Force $Path
	}

	$src = New-Object System.IO.FileInfo($Path + '.001')
	if($src.Exists) {
		$count = 1
		if($Text) {
			while(Test-Path ($Path + ($cnt = ('.{0:D3}' -f $count)))) {
				Get-Content ($Path + $cnt) >> $Path
				$count++;
			}
		} else {
			$dstFs = New-Object System.IO.FileStream($Path, 'Create')
			while(Test-Path ($Path + ($cnt = ('.{0:D3}' -f $count)))) {
				$buf = [System.IO.File]::ReadAllBytes($Path + $cnt)
				$dstFs.Write($buf, 0, $buf.Length)
				$count++;
			}
			$dstFs.Dispose()
		}
		$dst = New-Object System.IO.FileInfo($Path)
		$dst.LastWriteTime = $src.LastWriteTime
		$dst.Attributes = $src.Attributes
	}
}