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

http://tailforwin32.sourceforge.net/

and

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

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


当前回答

有许多有效的答案,但是,没有一个与linux中的tail具有相同的语法。下面的函数可以存储在$Home\Documents\PowerShell\Microsoft.PowerShell_profile中。Ps1的持久性(请参阅powershell概要文档了解更多详细信息)。

这允许你调用…

tail server.log
tail -n 5 server.log
tail -f server.log
tail -Follow -Lines 5 -Path server.log

这与Linux语法非常接近。

function tail {
<#
    .SYNOPSIS
        Get the last n lines of a text file.
    .PARAMETER Follow
        output appended data as the file grows
    .PARAMETER Lines
        output the last N lines (default: 10)
    .PARAMETER Path
        path to the text file
    .INPUTS
        System.Int
        IO.FileInfo
    .OUTPUTS
        System.String
    .EXAMPLE
        PS> tail c:\server.log
    .EXAMPLE
        PS> tail -f -n 20 c:\server.log
#>
    [CmdletBinding()]
    [OutputType('System.String')]
    Param(
        [Alias("f")]
        [parameter(Mandatory=$false)]
        [switch]$Follow,

        [Alias("n")]
        [parameter(Mandatory=$false)]
        [Int]$Lines = 10,

        [parameter(Mandatory=$true, Position=5)]
        [ValidateNotNullOrEmpty()]
        [IO.FileInfo]$Path
    )
    if ($Follow)
    {
        Get-Content -Path $Path -Tail $Lines -Wait
    }
    else
    {
        Get-Content -Path $Path -Tail $Lines
    }
}

其他回答

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

gc filename -wai -ta 10

对Get-Content使用-wait参数,它将显示添加到文件中的行。这个特性在PowerShell v1中就有了,但是由于某种原因在v2中没有很好地记录。

这里有一个例子

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

运行此命令后,更新并保存该文件,您将在控制台上看到更改。

有许多有效的答案,但是,没有一个与linux中的tail具有相同的语法。下面的函数可以存储在$Home\Documents\PowerShell\Microsoft.PowerShell_profile中。Ps1的持久性(请参阅powershell概要文档了解更多详细信息)。

这允许你调用…

tail server.log
tail -n 5 server.log
tail -f server.log
tail -Follow -Lines 5 -Path server.log

这与Linux语法非常接近。

function tail {
<#
    .SYNOPSIS
        Get the last n lines of a text file.
    .PARAMETER Follow
        output appended data as the file grows
    .PARAMETER Lines
        output the last N lines (default: 10)
    .PARAMETER Path
        path to the text file
    .INPUTS
        System.Int
        IO.FileInfo
    .OUTPUTS
        System.String
    .EXAMPLE
        PS> tail c:\server.log
    .EXAMPLE
        PS> tail -f -n 20 c:\server.log
#>
    [CmdletBinding()]
    [OutputType('System.String')]
    Param(
        [Alias("f")]
        [parameter(Mandatory=$false)]
        [switch]$Follow,

        [Alias("n")]
        [parameter(Mandatory=$false)]
        [Int]$Lines = 10,

        [parameter(Mandatory=$true, Position=5)]
        [ValidateNotNullOrEmpty()]
        [IO.FileInfo]$Path
    )
    if ($Follow)
    {
        Get-Content -Path $Path -Tail $Lines -Wait
    }
    else
    {
        Get-Content -Path $Path -Tail $Lines
    }
}

我采用了@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定义了别名,例如,如果您习惯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