J'ai besoin de récupérer les n dernières lignes de fichiers énormes (1-4 Go), dans Windows 7. En raison des restrictions de l'entreprise, je ne peux exécuter aucune commande qui n'est pas intégrée. Le problème est que toutes les solutions que j'ai trouvées semblent lire l'intégralité du fichier, elles sont donc extrêmement lentes.
Cela peut-il être accompli rapidement?
Remarques:
Solutions ici commande équivalente à la queue Unix dans Windows Powershell ne fonctionnait pas. En utilisant -wait
ne fait pas vite. Je n'ai pas -tail
(et je ne sais pas si cela fonctionnera rapidement).
PS: Il y a pas mal de questions liées à head
et tail
, mais pas centrées sur la question de la vitesse. Par conséquent, des réponses utiles ou acceptées peuvent ne pas être utiles ici. Par exemple.,
équivalent Windows de la commande 'tail'
Script batch CMD.EXE pour afficher les 10 dernières lignes d'un fichier txt
Extraire N lignes du fichier en utilisant la commande de fenêtres uniques
PowerShell pour obtenir les premiers x Mo d'un fichier
https://superuser.com/questions/859870/windows-equivalent-of-the-head-c-command
Que diriez-vous de cela (lit les 8 derniers octets pour la démo):
$fpath = "C:\10GBfile.dat"
$fs = [IO.File]::OpenRead($fpath)
$fs.Seek(-8, 'End') | Out-Null
for ($i = 0; $i -lt 8; $i++)
{
$fs.ReadByte()
}
MISE À JOUR . Pour interpréter les octets comme une chaîne (mais assurez-vous de sélectionner le bon codage - ici UTF8 est utilisé):
$N = 8
$fpath = "C:\10GBfile.dat"
$fs = [IO.File]::OpenRead($fpath)
$fs.Seek(-$N, [System.IO.SeekOrigin]::End) | Out-Null
$buffer = new-object Byte[] $N
$fs.Read($buffer, 0, $N) | Out-Null
$fs.Close()
[System.Text.Encoding]::UTF8.GetString($buffer)
MISE À JOUR 2. Pour lire les M dernières lignes, nous lirons le fichier par portions jusqu'à ce qu'il y ait plus de M séquences de caractères de nouvelle ligne dans le résultat:
$M = 3
$fpath = "C:\10GBfile.dat"
$result = ""
$seq = "`r`n"
$buffer_size = 10
$buffer = new-object Byte[] $buffer_size
$fs = [IO.File]::OpenRead($fpath)
while (([regex]::Matches($result, $seq)).Count -lt $M)
{
$fs.Seek(-($result.Length + $buffer_size), [System.IO.SeekOrigin]::End) | Out-Null
$fs.Read($buffer, 0, $buffer_size) | Out-Null
$result = [System.Text.Encoding]::UTF8.GetString($buffer) + $result
}
$fs.Close()
($result -split $seq) | Select -Last $M
Essayez de jouer avec de plus gros $buffer_size
- ceci est idéalement égal à la longueur de ligne moyenne attendue pour effectuer moins d'opérations sur le disque. Faites également attention à $ seq - cela pourrait être \r\n
ou juste \n
. C'est du code très sale sans aucune gestion d'erreur et optimisation.
Si vous avez PowerShell 3 ou supérieur, vous pouvez utiliser le -Tail
paramètre pour Get-Content
pour obtenir les dernières n
lignes.
Get-content -tail 5 PATH_TO_FILE;
Sur un fichier texte de 34 Mo sur mon SSD local, cela est revenu en 1 milliseconde contre 8,5 secondes pendant get-content |select -last 5
Avec la réponse impressionnante d'Aziz Kabyshev , qui résout le problème de la vitesse, et avec quelques recherches sur Google, j'ai fini par utiliser ce script
$fpath = $Args[1]
$fs = [IO.File]::OpenRead($fpath)
$fs.Seek(-$Args[0], 'End') | Out-Null
$mystr = ''
for ($i = 0; $i -lt $Args[0]; $i++)
{
$mystr = ($mystr) + ([char[]]($fs.ReadByte()))
}
$fs.Close()
Write-Host $mystr
que j'appelle à partir d'un fichier batch contenant
@PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '.\myscript.ps1' %1 %2"
(merci à Comment exécuter un script PowerShell à partir d'un fichier batch ).
Ce n'est pas une réponse, mais un grand commentaire comme réponse à la réponse de sancho.s.
Lorsque vous souhaitez utiliser de petits scripts PowerShell à partir d'un fichier Batch, je vous suggère d'utiliser la méthode ci-dessous, qui est plus simple et permet de conserver tout le code dans le même fichier Batch:
@PowerShell ^
$fpath = %2; ^
$fs = [IO.File]::OpenRead($fpath); ^
$fs.Seek(-%1, 'End') ^| Out-Null; ^
$mystr = ''; ^
for ($i = 0; $i -lt %1; $i++) ^
{ ^
$mystr = ($mystr) + ([char[]]($fs.ReadByte())); ^
} ^
Write-Host $mystr
%End PowerShell%