Unix-эквивалентная команда в Windows Powershell
Мне нужно посмотреть последние несколько строк большого файла (типичный размер - 500 МБ-2 ГБ). Я ищу эквивалент команды Unix tail
для Windows Powershell. Доступны несколько альтернатив,
http://tailforwin32.sourceforge.net/
и
Get-Content [filename] | Select-Object -Last 10
Для меня не разрешено использовать первый вариант, а второй вариант медленный. Кто-нибудь знает об эффективной реализации хвоста для PowerShell.
Ответы
Ответ 1
Используйте параметр -wait
с помощью Get-Content, который отображает строки по мере их добавления в файл. Эта функция присутствовала в PowerShell v1, но по какой-то причине не хорошо документирована в версии v2.
Вот пример
Get-Content -Path "C:\scripts\test.txt" -Wait
После запуска этого обновления обновите и сохраните файл, и вы увидите изменения на консоли.
Ответ 2
Как и в PowerShell версии 3.0, командлет Get-Content имеет параметр -Tail, который должен помочь. См. интерактивную справку по библиотеке технологий для Get-Content.
Ответ 3
Для полноты я упомянул, что у Powershell 3.0 теперь есть флаг -Tail в Get-Content
Get-Content ./log.log -Tail 10
получает последние 10 строк файла
Get-Content ./log.log -Wait -Tail 10
получает последние 10 строк файла и ждет больше
Ответ 4
Расширения сообщества 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.
Ответ 5
Я использовал некоторые из приведенных здесь ответов, но только хэдз-ап, которые
Get-Content -Path Yourfile.log -Tail 30 -Wait
через некоторое время пережевывает память. За последний день коллега покинул такой "хвост", и он поднялся до 800 МБ. Я не знаю, ведет ли хвост Unix одинаково (но я сомневаюсь). Поэтому он подходит для краткосрочных приложений, но будьте осторожны с ним.
Ответ 6
Просто некоторые дополнения к предыдущим ответам. Есть псевдонимы, определенные для 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
Ответ 7
Я принял решение @hajamie и завернул его в несколько более удобную оболочку script.
Я добавил возможность начать со смещения до конца файла, так что вы можете использовать хвостовую функцию для чтения определенной суммы с конца файла. Обратите внимание, что смещение находится в байтах, а не в строках.
Также существует возможность продолжить просмотр большего содержимого.
Примеры (если вы сохраните это как 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
И вот сам script...
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;
}
}
Ответ 8
Используя 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
}
Я нашел большую часть кода для этого здесь.
Ответ 9
Очень простой, но делает то, что вам нужно без каких-либо модулей аддонов или требований к версии PS:
while ($true) {Clear-Host; gc E:\test.txt | select -last 3; sleep 2 }
Ответ 10
попробуйте Windows Server 2003 Resource Kit Tools
содержит tail.exe
, который можно запустить в системе Windows.
https://www.microsoft.com/en-us/download/details.aspx?id=17657