Lệnh tương đương đuôi Unix trong Windows Powershell


349

Tôi phải xem xét một vài dòng cuối cùng của một tệp lớn (kích thước thông thường là 500MB-2GB). Tôi đang tìm kiếm một lệnh tương đương với Unix tailcho Windows Powershell. Một vài lựa chọn thay thế có sẵn trên là,

http://tailforwin32.sourceforge.net/

Nội dung [tên tệp] | Chọn-Object -Last 10

Đối với tôi, nó không được phép sử dụng thay thế đầu tiên, và thay thế thứ hai là chậm. Có ai biết về việc triển khai đuôi hiệu quả cho PowerShell không.


2
Làm thế nào chúng tôi có thể biết nếu bạn sẽ được phép sử dụng những gì chúng tôi đề xuất nếu bạn không nói lý do tại sao bạn không được phép sử dụng thay thế đầu tiên?
Gabe

3
Bất kỳ lý do nào bạn không thể sử dụng taillệnh được cung cấp trong sourceforge.net/projects/unxutils/files/unxutils/c Hiện / trên ?
Gabe

1
đây là trong một máy sản xuất mà tôi không được phép sao chép bất kỳ bản thực thi bên ngoài nào. Một số chính sách kỳ lạ. :) Không thể giúp nó. Cảm ơn các liên kết Unxutils.
mutelogan

https://devcentral.f5.com/bloss/us/unix-to-powershell-tail thể hiện việc thực hiện PoSH thuần túy của việc này.
Yevgeniy

Không cần sử dụng Chọn đối tượng: Get-Content [filename] -last 10và thêm -tailcho -f
MortenB

Câu trả lời:


492

Sử dụng -waittham số với Get-Content, hiển thị các dòng khi chúng được thêm vào tệp. Tính năng này đã có trong PowerShell v1, nhưng vì một số lý do không được ghi lại tốt trong v2.

Đây là một ví dụ

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

Khi bạn chạy nó, hãy cập nhật và lưu tệp và bạn sẽ thấy những thay đổi trên bàn điều khiển.


16
Hấp dẫn. Tôi đã nghĩ rằng tất cả các đối số tồn tại cũng xuất hiện trong trợ giúp, nhưng man gc -par waitcho tôi biết không có tham số. Nhưng tôi nghĩ điều này không giải quyết được vấn đề mà OP có, vì họ đã yêu cầu tail, không phải tail -fvà cũng là một triển khai hiệu quả. Vì cái này cũng đọc tệp hoàn chỉnh trước khi trả về các dòng cuối cùng, điều này gây đau khổ cho kích thước tệp mà họ mong đợi.
Joey

5
FYI, đây là những gì triển khai Get-FileTail (đuôi bí danh) làm trong PSCX. Nếu bạn tò mò, bạn có thể xem mã nguồn: pscx.codeplex.com/SourceControl/changeset/view/78514#1358075
Keith Hill

7
@Joey -Wait là một tham số động chỉ áp dụng cho nhà cung cấp FileSystem. GC có thể được sử dụng trên bất kỳ nhà cung cấp nào thực hiện API đó. Cách duy nhất ngoài tài liệu mà tôi biết để khám phá những điều này là sử dụng (gcm Get-Content) .Parameter từ bên trong đường dẫn nhà cung cấp thích hợp. Không sử dụng bí danh "gc" vì các tham số động sẽ không hiển thị.
JasonMArcher

11
Tôi biết cách đây một thời gian, nhưng điều này đòi hỏi quá trình ghi vào tệp để mở, nối thêm, đóng trước khi Get-Content hoạt động. Nếu quá trình viết không bao giờ đóng tệp thì nó sẽ không hoạt động, đó không phải là trường hợp với đuôi -f.
David Newcomb

15
Điều kỳ lạ là -Wait chỉ hiển thị cho tôi các dòng mới khi tôi truy cập tệp nhật ký theo một cách nào đó (chẳng hạn như chọn nó trong Windows Explorer). Tail cung cấp thông tin cập nhật khi các dòng mới được ghi vào tệp của tôi. Với -Wait, tôi có thể để cửa sổ PowerShell mở một cách vui vẻ hiển thị không có dòng mới nào trong khi tệp đang được ghi vào. Nếu sau đó tôi bật lên và nhấp vào tệp trong Windows Explorer, đột nhiên PowerShell "thức dậy" và bắt kịp các dòng còn lại. Đây có phải là một lỗi?
JoshL

197

Để hoàn thiện, tôi sẽ đề cập rằng Powershell 3.0 hiện có cờ -Tail trên Get-Content

Get-Content ./log.log -Tail 10

nhận được 10 dòng cuối cùng của tập tin

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

nhận được 10 dòng cuối cùng của tệp và chờ thêm

Ngoài ra, đối với những người dùng * nix, lưu ý rằng hầu hết các hệ thống bí danh mèo để Get-Content, vì vậy đây thường công trình

cat ./log.log -Tail 10

@LauraLiparulo theo cách này không hoạt động? Tôi đã sử dụng nó trước khi chắc chắn.
George Mauer

4
Tôi chỉ sử dụng nó và nó hoạt động tại định dạng nàyGet-Content .\test.txt -Wait -Tail 1
Coops

@LauraLiparulo - Cũng hoạt động với tôi:Get-Content -Path .\sync.log -Wait -Tail 10
elika kohen

Trên ISE, tôi đã từng sử dụng while ($ true) / ngủ và chuyển sang cái này, nhưng cái này cũng khóa toàn bộ ISE và không thể chạy tập lệnh trên các tab khác. Tôi có nên bắt đầu một ví dụ ISE mới không?
Teoman shipahi

@Teomanshipahi Theo cách nào thì -Waittham số không phù hợp với bạn?
George Mauer

116

Kể từ phiên bản PowerShell 3.0, lệnh ghép ngắn Get-Content có tham số -Tail sẽ giúp ích. Xem thư viện trợ giúp trực tuyến về Get-Content.


1
Liên kết để tải xuống tại đây - microsoft.com/en-us/doad/details.aspx?id=34595 .
Gedrox

4
Lưu ý đối với một số - PS 3.0 không khả dụng với Windows XP và Vista.
tjmoore

1
Tôi sử dụng kỹ thuật được đề cập bởi Dan nhưng tôi ghi lại nó trong $ HỒ SƠ. Mở nó bằng notepad $ PROFILE. Sau đó, trong tài liệu văn bản, tạo một hàm mới: function Tail ($ path) {Get-content -tail 15 -path $ path -wait} Bằng cách này bạn có thể truy cập chức năng mỗi khi bạn khởi động PowerShell.
Jake Nelson

Đây phải là câu trả lời được chấp nhận. Cờ -Wait được đề cập trong câu trả lời hiện được chấp nhận không hoạt động nữa.
Abdullah Leghari

21

Tôi đã sử dụng một số câu trả lời được đưa ra ở đây nhưng chỉ là một cái đầu

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

sẽ nhai lại ký ức sau một lúc. Một đồng nghiệp đã để lại một "cái đuôi" như vậy trong ngày qua và nó đã lên tới 800 MB. Tôi không biết đuôi Unix có hành xử giống như vậy không (nhưng tôi nghi ngờ điều đó). Vì vậy, nó tốt để sử dụng cho các ứng dụng ngắn hạn, nhưng hãy cẩn thận với nó.


18

Tiện ích mở rộng cộng đồng PowerShell (PSCX) cung cấp Get-FileTaillệnh ghép ngắn . Nó trông giống như một giải pháp phù hợp cho nhiệm vụ. Lưu ý: Tôi đã không thử nó với các tệp cực lớn nhưng mô tả cho biết nó có hiệu quả trong nội dung và nó được thiết kế cho các tệp nhật ký lớn.

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
Có một lỗi trong phiên bản hiện tại được sửa trong các bit hàng ngày. Tôi sẽ khuyên bạn nên lấy các bit mới nhất và biên dịch chúng ít nhất cho đến khi chúng tôi nhận được một phiên bản cập nhật được phát hành.
Keith Hill

7
Phiên bản 2.0 mất nhiều thời gian để hiển thị 10 dòng cuối cùng của tệp csv 1GB và khác với Get-Content [filename] | Select-Object -Last 10nó không thể bị hủy bỏ
Jader Dias

15

Chỉ cần một số bổ sung cho câu trả lời trước. Có các bí danh được định nghĩa cho Get-Content, ví dụ nếu bạn đã quen với UNIX bạn có thể thích cat, và cũng có typegc. Vì vậy, thay vì

Get-Content -Path <Path> -Wait -Tail 10

bạn có thể viết

# 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

Sử dụng Powershell V2 trở xuống, get-content đọc toàn bộ tệp, vì vậy nó không có tác dụng với tôi. Đoạn mã sau hoạt động cho những gì tôi cần, mặc dù có thể có một số vấn đề với mã hóa ký tự. Đây thực sự là đuôi -f, nhưng nó có thể dễ dàng được sửa đổi để lấy x byte cuối cùng hoặc x dòng cuối nếu bạn muốn tìm kiếm ngược để ngắt dòng.

$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
}

Tôi tìm thấy hầu hết các mã để làm điều này ở đây .


1
Có đúng là Get-Content với tùy chọn -Tail đọc toàn bộ tệp không? Trên các tập tin lớn có vẻ ổn đối với tôi.
Govert

Tôi tin rằng nó phụ thuộc vào phiên bản PS. Tôi đã cập nhật câu trả lời. Tôi đã bị mắc kẹt trên một máy chủ mà không có khả năng cài đặt bất cứ thứ gì vào thời điểm đó, vì vậy đoạn mã trên rất hữu ích.
hajamie

3

Tôi lấy giải pháp của @ hajamie và gói nó thành một trình bao bọc kịch bản thuận tiện hơn một chút.

Tôi đã thêm một tùy chọn để bắt đầu từ phần bù trước khi kết thúc tệp, vì vậy bạn có thể sử dụng chức năng giống như đuôi để đọc một số tiền nhất định từ cuối tệp. Lưu ý phần bù được tính bằng byte, không phải dòng.

Ngoài ra còn có một tùy chọn để tiếp tục chờ đợi thêm nội dung.

Ví dụ (giả sử bạn lưu cái này dưới dạng 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

Và đây là kịch bản ...

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

Rất cơ bản, nhưng thực hiện những gì bạn cần mà không cần bất kỳ mô-đun bổ trợ hoặc yêu cầu phiên bản PS nào:

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


4
Đó là tàn bạo trên các tập tin lớn.
Hóa đơn Pecos

Cách giải quyết của tôi là: while($true) { Clear-Host; Get-Content <filename> -tail 40; sleep 1 }:)
NoLifeKing

0

Có lẽ đã quá muộn cho một câu trả lời, nhưng hãy thử cái này

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

0

Đã có nhiều câu trả lời hợp lệ, tuy nhiên, không ai trong số họ có cùng một cú pháp như đuôi trong linux . Các chức năng sau đây có thể được lưu trữ trong $Home\Documents\PowerShell\Microsoft.PowerShell_profile.ps1sự kiên trì của bạn (xem tài liệu hồ sơ powershell để biết thêm chi tiết).

Điều này cho phép bạn gọi ...

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

mà đến khá gần với cú pháp 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
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.