Je dois regarder les dernières lignes d'un fichier volumineux (taille typique: 500 Mo - 2 Go). Je recherche un équivalent de la commande Unix tail
pour Windows Powershell. Quelques alternatives disponibles sur sont,
http://tailforwin32.sourceforge.net/
et
Get-Content [nom du fichier] | Select-Object -Last 10
Pour moi, il n'est pas permis d'utiliser la première alternative et la seconde alternative est lente. Est-ce que quelqu'un connaît une implémentation efficace de tail pour PowerShell?.
Utilisez le paramètre -wait
avec Get-Content, qui affiche les lignes au fur et à mesure qu'elles sont ajoutées au fichier. Cette fonctionnalité était présente dans PowerShell v1, mais pour une raison quelconque n’est pas bien documentée dans la v2.
Voici un exemple
Get-Content -Path "C:\scripts\test.txt" -Wait
Une fois que vous avez lancé ceci, mettez à jour et enregistrez le fichier et vous verrez les modifications sur la console.
Pour être complet, je mentionnerai que Powershell 3.0 a maintenant un drapeau -Tail sur Get-Content
Get-Content ./log.log -Tail 10
récupère les 10 dernières lignes du fichier
Get-Content ./log.log -Wait -Tail 10
obtient les 10 dernières lignes du fichier et attend plus
En outre, pour les utilisateurs * nix, notez que la plupart des systèmes alias cat to Get-Content, donc cela fonctionne généralement
cat ./log.log -Tail 10
Depuis la version 3.0 de PowerShell, la cmdlet Get-Content comporte un paramètre - Tail qui devrait vous aider. Voir l'aide en ligne de la bibliothèque technet pour Get-Content.
J'ai utilisé certaines des réponses données ici, mais juste un avertissement qui
Get-Content -Path Yourfile.log -Tail 30 -Wait
va mâcher la mémoire après un certain temps. Un collègue a laissé une telle "queue" au cours de la dernière journée pour atteindre 800 Mo. Je ne sais pas si Unix tail se comporte de la même manière (mais j'en doute). Donc, c'est bien d'utiliser pour des applications à court terme, mais soyez prudent avec cela.
Les extensions de communauté PowerShell (PSCX) fournit la Get-FileTail
cmdlet . Cela semble être une solution adaptée à la tâche. Remarque: je ne l'ai pas essayé avec des fichiers extrêmement volumineux, mais la description indique que le contenu en est réduit au minimum et qu'il est conçu pour les fichiers journaux volumineux.
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.
Juste quelques ajouts aux réponses précédentes. Il existe des alias définis pour Get-Content. Par exemple, si vous êtes habitué à UNIX, vous pourriez aimer cat
, et il y a aussi type
et gc
. Donc au lieu de
Get-Content -Path <Path> -Wait -Tail 10
tu peux écrire
# 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
À l'aide de Powershell version 2 et antérieure, get-content lit l'intégralité du fichier, ce qui ne m'a donc servi à rien. Le code suivant fonctionne pour ce dont j'avais besoin, bien qu'il y ait probablement des problèmes avec les encodages de caractères. C'est effectivement tail -f, mais il pourrait être facilement modifié pour obtenir les x derniers octets, ou les dernières x lignes si vous souhaitez rechercher des sauts de ligne en arrière.
$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
}
J'ai trouvé la plupart du code pour faire ceci ici .
J'ai pris la solution de @ hajamie et l'ai emballée dans un wrapper de script légèrement plus pratique.
J'ai ajouté une option permettant de démarrer à partir d'un décalage avant la fin du fichier. Vous pouvez donc utiliser la fonctionnalité similaire à la lecture d'une certaine quantité à partir de la fin du fichier. Notez que le décalage est en octets et non en lignes.
Il existe également une option pour continuer à attendre pour plus de contenu.
Exemples (en supposant que vous enregistrez ceci sous 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
Et voici le script lui-même ...
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;
}
}
essayez Windows Server 2003 Resource Kit Tools
il contient un tail.exe
qui peut être exécuté sur le système Windows.
https://www.Microsoft.com/en-us/download/details.aspx?id=17657
Très basique, mais fait ce dont vous avez besoin sans modules additionnels ni exigences de version PS:
while ($true) {Clear-Host; gc E:\test.txt | select -last 3; sleep 2 }
Probablement trop tard pour une réponse mais essayez celui-ci
Get-Content <filename> -tail <number of items wanted>