if ($operation -in @('head', 'tail')) { $linesWanted = 10; $paths = [Collections.Generic.List[string]]::new() for ($i = 0; $i -lt $toolArgs.Count; $i++) { $arg = $toolArgs[$i] if ($arg -in @('-n', '--lines')) { $i += 1; if ($i -ge $toolArgs.Count) { Fail ($arg + ' requires a value') 2 }; $linesWanted = Parse-NonNegativeInt $arg $toolArgs[$i] 10000; continue } if ($arg.StartsWith('-n') -and $arg.Length -gt 2) { $linesWanted = Parse-NonNegativeInt '-n' $arg.Substring(2) 10000; continue } if ($arg.StartsWith('--lines=')) { $linesWanted = Parse-NonNegativeInt '--lines' $arg.Substring(8) 10000; continue } if ($arg -match '^-(\d+)$') { $linesWanted = Parse-NonNegativeInt ('-' + $Matches[1]) $Matches[1] 10000; continue } if ($arg.StartsWith('-') -and $arg -ne '-') { Fail ('unsupported ' + $operation + ' option on Windows route: ' + $arg) 2 } $paths.Add($arg) } if ($paths.Count -ne 1) { Fail ($operation + ' requires exactly one file path on Windows routes') 2 } $resolved = Resolve-UnideskPath $paths[0] Need-File $resolved $selected = [Collections.Generic.List[string]]::new() $reader = [IO.StreamReader]::new($resolved, [Text.UTF8Encoding]::new($false, $true), $true) try { if ($operation -eq 'head') { while ($selected.Count -lt $linesWanted -and -not $reader.EndOfStream) { $selected.Add($reader.ReadLine()) } } else { $queue = [Collections.Generic.Queue[string]]::new() while (-not $reader.EndOfStream) { $queue.Enqueue($reader.ReadLine()) if ($queue.Count -gt $linesWanted) { [void]$queue.Dequeue() } } foreach ($line in $queue) { $selected.Add($line) } } } catch { Fail ('file is not valid UTF-8: ' + $resolved + ': ' + $_.Exception.Message) 25 } finally { $reader.Dispose() } Print-Lines ([string[]]$selected) exit 0 }