Это также может быть выполнимо с помощью встроенных командлетов, но я бы опасался запускать Get-Content
файлы размером более 100 МБ. Если вы хотите попробовать, вы можете захотеть эквивалент дляtail
. Я не уверен, достаточно ли они умны, чтобы пропустить вперед, или они пытаются прочитать каждую строку с самого начала и отображать только последние X строк. Очевидно, что последний подход займет некоторое время, если он попытается прочитать и пропустить 90+ ГБ.
Если вас не интересуют инструменты, встроенные в Windows, я считаю, что tail
реализация GNU умнее. Это может быть запущено из WSL или одного из множества портов.
Придерживаясь только сценариев PowerShell / .NET, я адаптирую предыдущий сценарий PowerShell, предназначенный для разделения одного большого файла. Этот сценарий был написан для использования блоков по 4 КБ, минимизируя использование памяти. Сначала мы можем найти правильное местоположение (почти мгновенная операция) и скопировать оттуда. Для простоты не выполняется синтаксический анализ следующего / предыдущего разрыва строки ; мы просто прыгаем на определенный байт (даже в середине строки).
Если вы предпочитаете искать определенное расстояние с самого начала, вы можете, например, заменить $seekLoc = 97GB
и $seekOrigin = "Begin"
, и, возможно, $copyLen = 10GB
быть в безопасности и не пропустить конец.
$inFile = "foo.txt" $outFile = "bar.txt" $seekLoc = -1GB $seekOrigin = "End" $copyLen = 1GB # need to sync .NET CurrentDirectory with PowerShell CurrentDirectory # https://stackoverflow.com/questions/18862716/current-directory-from-a-dll-invoked-from-powershell-wrong [Environment]::CurrentDirectory = Get-Location # 4k is a fairly typical and 'safe' chunk size # partial chunks are handled below $bytes = New-Object byte[] 4096 $inReader = [System.IO.File]::OpenRead($inFile) $inReader.Seek($seekLoc, $seekOrigin) # better to use functions but a flag is easier in a simple script $finished = $false $bytesToRead = $copyLen # Just like File::OpenWrite except CreateNew instead to prevent overwriting existing files $outWriter = New-Object System.IO.FileStream "$outFile",CreateNew,Write,None while ($bytesToRead) { # read up to 4k at a time, but no more than the remaining bytes from copyLen $bytesRead = $inReader.Read($bytes, 0, [Math]::Min($bytes.Length, $bytesToRead)) # 0 bytes read means we've reached the end of the input file if (!$bytesRead) { break } $bytesToRead -= $bytesRead $outWriter.Write($bytes, 0, $bytesRead) } # dispose closes the stream and releases locks $outWriter.Dispose() $inReader.Dispose()