我必须查看一个大文件(典型大小为500MB-2GB)的最后几行。我正在寻找一个相当于Unix命令尾Windows Powershell。一些可供选择的方法是,

http://tailforwin32.sourceforge.net/

and

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

对于我来说,第一种选择是不允许使用的,而第二种选择是很慢的。有人知道PowerShell的tail的有效实现吗?


当前回答

我采用了@hajamie的解决方案,并将其包装到一个更方便的脚本包装器中。

我添加了一个选项,从文件结束之前的偏移量开始,因此您可以使用类似尾部的功能,从文件结束处读取一定量的数据。注意偏移量是以字节为单位的,而不是行。

你还可以选择继续等待更多内容。

示例(假设您将其保存为TailFile.ps1):

.\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;
    }
}

其他回答

也许现在回答已经太迟了,但是试试这个

Get-Content <filename> -tail <number of items wanted> -wait

对于那些以“打字越少越好”为原则的管理员来说,下面是我能找到的最短版本:

gc filename -wai -ta 10

我采用了@hajamie的解决方案,并将其包装到一个更方便的脚本包装器中。

我添加了一个选项,从文件结束之前的偏移量开始,因此您可以使用类似尾部的功能,从文件结束处读取一定量的数据。注意偏移量是以字节为单位的,而不是行。

你还可以选择继续等待更多内容。

示例(假设您将其保存为TailFile.ps1):

.\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 Community Extensions (PSCX)提供了Get-FileTail cmdlet。这看起来是一个适合这项任务的解决方案。注意:我没有尝试它与非常大的文件,但描述说,它有效地尾部内容,它是为大型日志文件设计的。

NAME
    Get-FileTail

SYNOPSIS
    PSCX Cmdlet: Tails the contents of a file - optionally waiting on new content.

SYNTAX
    Get-FileTail [-Path] <String[]> [-Count <Int32>] [-Encoding <EncodingParameter>] [-LineTerminator <String>] [-Wait] [<CommonParameters>]

    Get-FileTail [-LiteralPath] <String[]> [-Count <Int32>] [-Encoding <EncodingParameter>] [-LineTerminator <String>] [-Wait] [<CommonParameters>]

DESCRIPTION
    This implentation efficiently tails the cotents of a file by reading lines from the end rather then processing the entire file. This behavior is crucial for ef
    ficiently tailing large log files and large log files over a network.  You can also specify the Wait parameter to have the cmdlet wait and display new content
    as it is written to the file.  Use Ctrl+C to break out of the wait loop.  Note that if an encoding is not specified, the cmdlet will attempt to auto-detect the
     encoding by reading the first character from the file. If no character haven't been written to the file yet, the cmdlet will default to using Unicode encoding
    . You can override this behavior by explicitly specifying the encoding via the Encoding parameter.

关于这个主题,我有一个关于多个文件的有用提示。

使用PowerShell 5.2 (Win7和Win10)跟踪单个日志文件(如Linux中的'tail -f')很容易(只需使用“Get-Content MyFile -Tail 1 -Wait”)。然而,同时查看多个日志文件似乎很复杂。PowerShell 7。x+然而,我发现了一个简单的方法,使用“Foreach-Object - parallel”。这将同时执行多个“Get-Content”命令。例如:

Get-ChildItem C:\logs\*.log | Foreach-Object -Parallel { Get-Content $_ -Tail 1 -Wait }