Windows Powershell中的Unix tail等效命令


349

我必须查看大文件的最后几行(通常大小为500MB-2GB)。我正在寻找tailWindows Powershell 的等效Unix命令。有几种可用的替代方法,

http://tailforwin32.sourceforge.net/

获取内容[文件名] | 选择对象-最后10个

对我来说,不允许使用第一种选择,第二种选择很慢。有谁知道PowerShell的tail的高效实现。


2
如果您不说为什么不使用第一个替代方法,我们如何知道您是否可以使用我们建议的方法?
加布

3
有什么原因不能使用sourceforge.net/projects/unxutils/files/unxutils/current/…中tail提供的命令?
加布

1
这是在生产机器中,不允许我复制任何外部可执行文件。一些奇怪的政策。:)无法帮助。感谢您的Unxutils链接。
Mutlogan 2010年


无需使用Select-Object:Get-Content [filename] -last 10并添加-tail-f
MortenB,

Answers:


492

-wait参数与Get-Content一起使用,在将行添加到文件中时会显示该行。PowerShell v1中存在此功能,但是由于某些原因,v2中没有对此文档进行很好的记录。

这是一个例子

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

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


16
有趣。我本以为所有存在的参数也会出现在帮助中,但man gc -par wait告诉我没有参数。但是我认为这并不能解决OP所存在的问题,因为他们要求的tail不是tail -f有效的实现。由于此文件在返回最后几行之前还读取了完整的文件,因此对于他们期望的文件大小来说很痛苦。
乔伊,2010年

5
仅供参考,这就是PSCX中Get-FileTail(别名尾部)实现的功能。如果您好奇,可以查看源代码:pscx.codeplex.com/SourceControl/changeset/view/78514#1358075
Keith Hill 2010年

7
@Joey -Wait是仅适用于FileSystem提供程序的动态参数。GC可以在实现该API的任何提供程序上使用。除了我知道发现这些文档的唯一方法,是在适当的提供程序路径中使用(gcm Get-Content).Parameters。不要使用别名“ gc”,因为动态参数不会显示。
JasonMArcher 2010年

11
我知道这是前一阵子,但这需要在写入文件之前打开,追加,关闭文件,然后才能使用Get-Content。如果写入过程从不关闭文件,那么它将无法正常工作,而尾-f则不然。
David Newcomb 2012年

15
奇怪的是,-Wait仅在我以某种方式(例如在Windows资源管理器中选择它)访问日志文件时才显示新行。当新行写入我的文件时,尾部将提供更新。使用-Wait,我可以使PowerShell窗口保持打开状态,愉快地显示在写入文件时没有新行。如果随后弹出窗口,然后单击Windows资源管理器中的文件,则PowerShell突然“醒来”并赶上其余行。这是错误吗?
JoshL 2012年

197

为了完整起见,我将提到Powershell 3.0现在在Get-Content上具有-Tail标志

Get-Content ./log.log -Tail 10

获取文件的最后10行

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

获取文件的最后10行并等待更多

另外,对于那些* nix用户,请注意,大多数系统将cat别名为Get-Content,因此通常可以使用

cat ./log.log -Tail 10

@LauraLiparulo用什么方式不起作用?我肯定以前用过。
George Mauer 2014年

4
我只是用过它,就以这种格式使用了它Get-Content .\test.txt -Wait -Tail 1
Coops 2014年

@LauraLiparulo-也为我工作:Get-Content -Path .\sync.log -Wait -Tail 10
elika kohen

在ISE上,我曾经使用while($ true)/ sleep并切换到该选项,但是此选项也锁定了整个ISE,无法在其他选项卡上运行脚本。我应该只启动一个新的ISE实例吗?
Teoman shipahi

@Teomanshipahi该-Wait参数不适用于您吗?
乔治·莫尔

116

从PowerShell版本3.0开始,Get-Content cmdlet具有应提供帮助的-Tail参数。请参阅Technet库在线帮助以获取内容。



4
某些注意事项-Windows XP和Vista无法使用PS 3.0。
tjmoore 2013年

1
我使用了Dan提到的技术,但将其记录在$ PROFILE中。用记事本$ PROFILE打开它。然后在文本文档中,创建一个新函数:function Tail($ path){Get-content -tail 15 -path $ path -wait}这样,您可以在每次启动PowerShell时访问该函数。
杰克·纳尔逊

这应该是公认的答案。-当前接受的答案中提到的等待标志不再起作用。
阿卜杜拉·莱加里

21

我使用了这里给出的一些答案,但请注意

Get-Content -Path Yourfile.log -Tail 30 -Wait 

过一会儿会消耗掉记忆。一位同事在最后一天留下了这样的“尾巴”,然后增加到800 MB。我不知道Unix尾巴的行为是否相同(但我对此表示怀疑)。因此,适用于短期应用程序很好,但是要小心。


18

PowerShell社区扩展(PSCX)提供了Get-FileTailcmdlet。看起来像是适合该任务的解决方案。注意:我没有尝试使用非常大的文件,但是描述说它有效地尾随内容,并且它是为大型日志文件设计的。

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.

1
当前版本中存在一个错误,该错误已逐日修复。我建议抓住最新的东西并至少在我们发布更新版本之前进行编译。
基思·希尔

7
2.0版需要很长时间才能显示1GB csv文件的最后10行,并且与Get-Content [filename] | Select-Object -Last 10它不能被中止的方式不同
Jader Dias

15

只是先前答案的一些补充。有为Get-Content定义的别名,例如,如果您习惯使用UNIX,则可能cat还有typegc。所以代替

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

3

使用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
}

我在这里找到了大多数代码来执行此操作。


1
具有-Tail选项的Get-Content是否读取整个文件,这是真的吗?对于大文件,对我来说似乎还可以。
Govert 2015年

我相信这取决于PS版本。我已经更新了答案。我被困在无法安装任何东西的服务器上,因此上面的代码很有用。
hajamie 2015年

3

我采用了@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;
    }
}


0

非常基本,但是不需要任何附加模块或PS版本要求就可以满足您的需求:

while ($true) {Clear-Host; gc E:\test.txt | select -last 3; sleep 2 }


4
这对大文件而言是残酷的。
Pecos Bill

我的解决方法是:while($true) { Clear-Host; Get-Content <filename> -tail 40; sleep 1 }:)
NoLifeKing '17


0

有很多有效的答案,但是,没有一个与linux中tail的语法相同。可以将以下功能存储在您的设备中以保持持久性(请参阅Powershell配置文件文档)$Home\Documents\PowerShell\Microsoft.PowerShell_profile.ps1有关更多详细信息,)。

这使您可以致电...

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
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.