Windows Powershell中的Unix tail等效命令

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

http://tailforwin32.sourceforge.net/ < a href = " http://tailforwin32.sourceforge.net/ " > < / >

而且

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

For me, it is not allowed to use the first alternative, and the second alternative is slow. Does anyone know of an efficient implementation of tail for PowerShell.

426724 次浏览

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

这里有一个例子

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

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

PowerShell社区扩展(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 3.0版开始,Get-Content cmdlet有一个多边形参数,这应该会有所帮助。看到technet图书馆在线帮助Get-Content。

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

Get-Content ./log.log -Tail 10

获取文件的最后10行

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

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

另外,对于那些*nix用户,请注意大多数系统别名为Get-Content,所以这通常是有效的

cat ./log.log -Tail 10

非常基本,但不需要任何附加模块或PS版本要求:

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

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

我发现大部分代码来做这个在这里

只是对之前答案的补充。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

我采用了@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 -Path Yourfile.log -Tail 30 -Wait

会在一段时间后咀嚼记忆。一个同事在过去的一天里留下了这样一个“尾巴”,它高达800 MB。我不知道Unix尾巴是否也有同样的行为(但我怀疑)。所以短期使用是可以的,但要小心。

尝试Windows Server 2003 Resource Kit Tools

它包含一个tail.exe,可以在Windows系统上运行。

https://www.microsoft.com/en-us/download/details.aspx?id=17657

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

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

有很多有效的答案,但是,没有一个是相同语法的。下面的函数可以存储在你的$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
}
}

可以从这个GitHub存储库https://github.com/George-Ogden/UNIX下载为Windows编译的所有UNIX命令

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

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

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

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

gc filename -wai -ta 10