Эквивалентная команда хвоста Unix в Windows Powershell

Я должен посмотреть последние несколько строк большого файла (типичный размер 500MB-2GB). Я ищу эквивалент команды Unix tail для Windows Powershell. Несколько альтернатив, доступных на,

http://tailforwin32.sourceforge.net/

и

Get-Content [filename] | Select-Object -Last 10

для меня не разрешено использовать первую альтернативу, а вторая альтернатива медленная. Кто-нибудь знает об эффективной реализации tail для В PowerShell.

10 ответов


использовать -wait параметр с Get-Content, который отображает строки по мере их добавления в файл. Эта функция присутствовала в PowerShell v1, но по какой-то причине не была хорошо документирована в v2.

вот пример

Get-Content -Path "C:\scripts\test.txt" -Wait

после запуска обновите и сохраните файл,и вы увидите изменения на консоли.


для полноты я упомяну, что Powershell 3.0 теперь имеет флаг-Tail на Get-Content

Get-Content ./log.log -Tail 10

получает последние 10 строк файла

Get-Content ./log.log -Wait -Tail 10

получает последние 10 строк файла и ждет более


начиная с PowerShell версии 3.0 командлет Get-Content имеет хвост



я использовал некоторые из ответов, приведенных здесь, но просто предупреждает, что

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 считывает весь файл, поэтому он не был мне полезен. Следующий код работает для того, что мне нужно, хотя, вероятно, есть некоторые проблемы с кодировками символов. Это фактически хвост-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