Хвостовая эквивалентная команда Unix в Windows Powershell
Я должен посмотреть на последние несколько строк большого файла (типичный размер 500 МБ-2 ГБ). Я ищу эквивалент команды Unix tail
для Windows Powershell. Несколько вариантов, доступных на являются,
http://tailforwin32.sourceforge.net/
и
Get-Content [filename] | Select-Object -Last 10
для меня не разрешается использовать первую альтернативу, а вторая альтернатива медленная. Кто-нибудь знает об эффективной реализации хвоста для В PowerShell.
10 ответов:
использовать
-wait
параметр с Get-Content, который отображает строки по мере их добавления в файл. Эта функция присутствовала в PowerShell v1, но по какой-то причине не описанной в П2.вот пример
Get-Content -Path "C:\scripts\test.txt" -Wait
Как только вы запустите это обновление и сохраните файл, и вы увидите изменения на консоли.
для полноты я упомяну, что Powershell 3.0 теперь имеет флаг-хвост на Get-Content
Get-Content ./log.log -Tail 10
получает последние 10 строк файла
Get-Content ./log.log -Wait -Tail 10
получает последние 10 строк файла и ждет более
расширения сообщества PowerShell (PSCX) предоставляет
я использовал некоторые из ответов, приведенных здесь, но просто предупреждает, что
Get-Content -Path Yourfile.log -Tail 30 -Wait
будет жевать память через некоторое время. Коллега оставил такой "хвост" за последний день, и он поднялся до 800 МБ. Я не знаю, ведет ли хвост Unix таким же образом (но я сомневаюсь в этом). Так что это нормально использовать для краткосрочных приложений, но будьте осторожны с ним.
просто некоторые дополнения к предыдущим ответам. Существуют псевдонимы, определенные для Get-Content, например, если вы привыкли к UNIX, вам может понравиться
cat
, а такжеtype
иgc
. Так что вместоGet-Content -Path <Path> -Wait -Tail 10
можно писать
# Print whole file and wait for appended lines and print them cat <Path> -Wait # Print last 10 lines and wait for appended lines and print them cat <Path> -Tail 10 -Wait
Я взял решение @hajamie и завернул его в немного более удобную обертку сценария.
я добавил опцию, чтобы начать от смещения до конца файла, так что вы можете использовать хвост, как функциональность чтения определенной суммы от конца файла. Обратите внимание, что смещение находится в байтах, а не в строках.
есть также возможность продолжать ждать больше контента.
примеры (предполагая, что вы сохраните это как TailFile.пс1):
.\TailFile.ps1 -File .\path\to\myfile.log -InitialOffset 1000000 .\TailFile.ps1 -File .\path\to\myfile.log -InitialOffset 1000000 -Follow:$true .\TailFile.ps1 -File .\path\to\myfile.log -Follow:$true
а вот и сам скрипт...
param ( [Parameter(Mandatory=$true,HelpMessage="Enter the path to a file to tail")][string]$File = "", [Parameter(Mandatory=$true,HelpMessage="Enter the number of bytes from the end of the file")][int]$InitialOffset = 10248, [Parameter(Mandatory=$false,HelpMessage="Continuing monitoring the file for new additions?")][boolean]$Follow = $false ) $ci = get-childitem $File $fullName = $ci.FullName $reader = new-object System.IO.StreamReader(New-Object IO.FileStream($fullName, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [IO.FileShare]::ReadWrite)) #start at the end of the file $lastMaxOffset = $reader.BaseStream.Length - $InitialOffset while ($true) { #if the file size has not changed, idle if ($reader.BaseStream.Length -ge $lastMaxOffset) { #seek to the last max offset $reader.BaseStream.Seek($lastMaxOffset, [System.IO.SeekOrigin]::Begin) | out-null #read out of the file until the EOF $line = "" while (($line = $reader.ReadLine()) -ne $null) { write-output $line } #update the last max offset $lastMaxOffset = $reader.BaseStream.Position } if($Follow){ Start-Sleep -m 100 } else { break; } }
используя Powershell V2 и ниже, get-content считывает весь файл, поэтому мне это было бесполезно. Следующий код работает для того, что мне нужно, хотя, вероятно, есть некоторые проблемы с кодировками символов. Это эффективно tail-f, но его можно легко изменить, чтобы получить последние X байтов или последние X строк, если вы хотите выполнить поиск в обратном направлении для разрывов строк.
$filename = "\wherever\your\file\is.txt" $reader = new-object System.IO.StreamReader(New-Object IO.FileStream($filename, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [IO.FileShare]::ReadWrite)) #start at the end of the file $lastMaxOffset = $reader.BaseStream.Length while ($true) { Start-Sleep -m 100 #if the file size has not changed, idle if ($reader.BaseStream.Length -eq $lastMaxOffset) { continue; } #seek to the last max offset $reader.BaseStream.Seek($lastMaxOffset, [System.IO.SeekOrigin]::Begin) | out-null #read out of the file until the EOF $line = "" while (($line = $reader.ReadLine()) -ne $null) { write-output $line } #update the last max offset $lastMaxOffset = $reader.BaseStream.Position }
Я нашел большую часть кода, чтобы сделать это здесь.
очень простой, но делает то, что вам нужно без каких-либо аддон модулей или требований к версии PS:
while ($true) {Clear-Host; gc E:\test.txt | select -last 3; sleep 2 }
попробовать
Windows Server 2003 Resource Kit Tools
содержит
tail.exe
который может быть запущен в системе Windows.https://www.microsoft.com/en-us/download/details.aspx?id=17657