Windows PowerShellのUnixテール相当コマンド


349

大きなファイルの最後の数行を見なければなりません(通常のサイズは500MB〜2GBです)。tailWindows PowerShellのUnixコマンドに相当するものを探しています。利用可能ないくつかの選択肢は、

http://tailforwin32.sourceforge.net/

そして

Get-Content [ファイル名] | Select-Object -Last 10

私にとって、最初の選択肢を使用することはできません。2番目の選択肢は遅いです。PowerShellのtailの効率的な実装を知っている人はいますか?


2
最初の代替案の使用が許可されていない理由を言わない場合、提案されたものを使用できるかどうかをどのようにして知ることができますか?
Gabe

3
sourceforge.net/projects/unxutils/files/unxutils/current/…でtail提供されるコマンドを使用できない理由がありますか?
Gabe

1
これは、外部の実行可能ファイルをコピーコピーすることを許可されていない実稼働マシンにあります。いくつかの奇妙なポリシー。:)それを助けることはできません。Unxutilsリンクをありがとう。
mutelogan 2010

https://devcentral.f5.com/blogs/us/unix-to-powershell-tailは、これの純粋なPoSH実装を示しています。
Yevgeniy 2013年

Select-Object:を使用する必要はなく、-f Get-Content [filename] -last 10を追加-tailします
MortenB

回答:


492

-waitファイルに追加された行を表示するGet-Contentでパラメーターを使用します。この機能はPowerShell v1に存在していましたが、何らかの理由でv2では十分に文書化されていません。

ここに例があります

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

これを実行したら、ファイルを更新して保存すると、コンソールに変更が表示されます。


16
面白い。存在するすべての引数もヘルプに表示されると思いman gc -par waitましたが、パラメータはありません。しかし、私は彼らが尋ねたので、これは、OPが持っている問題を解決しないと思うtail、ではないtail -fだけでなく、効率的な実装。これも最後の行を返す前に完全なファイルを読み取るので、これは彼らが期待するファイルサイズにとって苦痛です。
Joey、

5
ちなみに、これはPSCXでのGet-FileTail(エイリアステール)の実装です。興味がある場合は、ソースコードを確認できます。pscx.codeplex.com
Keith Hill

7
@Joey -Waitは、FileSystemプロバイダーにのみ適用される動的パラメーターです。GCは、そのAPIを実装する任意のプロバイダーで使用できます。これらを発見するために私が知っているドキュメント以外の唯一の方法は、適切なプロバイダーパス内から(gcm Get-Content).Parametersを使用することです。動的パラメーターが表示されないため、エイリアス「gc」を使用しないでください。
JasonMArcher、2010

11
少し前のことですが、Get-Contentが機能する前に、ファイルを開いて追加し、閉じるためにファイルに書き込むプロセスが必要です。書き込みプロセスがファイルを閉じない場合、機能しません。これは、tail -fの場合とは異なります。
David Newcomb

15
奇妙なことに、-Waitは、何らかの方法(Windowsエクスプローラーでの選択など)でログファイルにアクセスしたときにのみ新しい行を表示します。新しい行がファイルに書き込まれると、Tailは更新を提供します。-Waitを使用すると、PowerShellウィンドウを開いたままにして、ファイルへの書き込み中に新しい行が表示されないようにすることができます。その後、Windows Explorerでファイルをポップしてクリックすると、突然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はこれがどのように機能しないのですか?間違いなく以前に使ったことがあります。
ジョージマウアー2014

4
私はそれを使用しただけで、このフォーマットでうまく機能しましたGet-Content .\test.txt -Wait -Tail 1
Coops

@LauraLiparulo-私にもGet-Content -Path .\sync.log -Wait -Tail 10
有効

ISEでは、while($ true)/ sleepを使用してこれに切り替えましたが、これもISE全体をロックし、他のタブでスクリプトを実行できません。新しいISEインスタンスを開始する必要がありますか?
Teoman Shipahi 2017

@Teomanshipahiどのような方法で-Waitパラメーターが機能しなかったのですか?
George Mauer

116

PowerShellバージョン3.0以降、Get-Contentコマンドレットには-Tailパラメーターがあり、これが役立つはずです。Get-Contentについては、technetライブラリのオンラインヘルプを参照してください


1
ここにダウンロードするためのリンク– microsoft.com/en-us/download/details.aspx?id=34595
Gedrox 2013年

4
一部の注意事項-PS 3.0はWindows XPおよびVistaでは使用できません。
tjmoore 2013年

1
Danが述べた手法を使用していますが、$ PROFILEに記録しています。メモ帳$ PROFILEで開きます。次に、テキストドキュメントで新しい関数を作成します。function Tail($ path){Get-content -tail 15 -path $ path -wait}この方法で、PowerShellを起動するたびに関数にアクセスできます。
ジェイクネルソン

これは受け入れられる答えになるはずです。-現在受け入れられている回答に記載されている待機フラグが機能しなくなりました。
Abdullah Leghari 2017年

21

私はここに与えられた答えのいくつかを使用しましたが、それはあくまでも前向きです

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

しばらくすると記憶をかむでしょう。同僚が最後の日にそのような「尻尾」を残して、それは800 MBになりました。Unixテールが同じように動作するかどうかはわかりません(しかし、疑わしいです)。したがって、短期間のアプリケーションで使用しても問題ありませんが、注意してください。


18

PowerShell Community Extensions(PSCX)は、Get-FileTailコマンドレットを提供します。タスクに適したソリューションのように見えます。注:私は極端に大きなファイルでそれを試しませんでしたが、説明によるとコンテンツを効率的に追尾し、大きなログファイル用に設計されています。

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では、1 GBのcsvファイルの最後の10行を表示するまでに時間がかかりますが、それとは異なり、Get-Content [filename] | Select-Object -Last 10中止することはできません
Jader Dias

15

以前の回答へのほんの一部の追加。あなたがUNIXに使用されている場合あなたが好きかもしれないたとえば、Get-コンテンツ用に定義されたエイリアスがあり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がファイル全体を読み取るのは本当ですか?大きなファイルでは私には問題ないようです。
2015

PSのバージョン次第だと思います。答えを更新しました。何もインストールできないサーバーで立ち往生していたため、上記のコードは役に立ちました。
ハジャミー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 2017年

0

おそらく回答には遅すぎますが、これを試してください

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

0

多くの有効な回答がありましたが、それらのどれもlinuxのテールと同じ構文を持ちません。次の関数は永続化のためにに保存できます(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
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.