PowerShellのGet-Contentコマンドの詳細ガイド:5つの実用的な例で理解する

PowerShellのGet-Contentコマンドの詳細ガイド:5つの実用的な例で理解するを安全に進める結論は「Get-Contentはfileを行またはraw文字列として読み取るcommandです。先頭・末尾・件数を限定して内容とencodingを確認し、監視は-Tailと-Wait、構造保持が必要なJSONやCSVは専用cmdletへ渡します。」です。Windows PowerShell 5.1とPowerShell 7.xで既定encodingの差を意識し、large logは全件をmemoryへ載せないという前提を外すと同じ入力でも結果が変わります。まず少量をread-onlyで取得し、型とencodingを確認してから読取範囲を広げます。

目次

読取前にpath・size・encodingを確かめる

Get-Contentでファイルを読む前に、LiteralPath、ファイルサイズ、文字コード、改行形式を確認します。全体を一つの文字列として扱うRaw、末尾監視のTail、分割単位を変えるReadCountでは戻り値の型と件数が異なります。小さなサンプルで型を表示し、巨大ファイルを不用意にメモリーへ載せない構成を選びます。

  • Get-Itemでpath、size、LastWriteTime、属性を確認する
  • Get-Content -TotalCount 5で少量を読み文字化けを確認する
  • Get-Help Get-Content -Parameter Encodingで利用版の候補を確認する
  • 機密logをconsole、transcript、ticketへ露出しない

行配列・Raw文字列・byte列の型を分ける

既定では一行ずつ文字列objectが流れます。配列indexは0から始まるため、先頭行はindex 0です。件数を安定して調べるには、小さなfileで @(Get-Content -LiteralPath …) のように配列として受けます。-Rawは改行を含む一つの文字列、-ReadCount 0は全行をまとめた出力になるため、large fileではmemory負荷を確認します。文字列のLengthはUTF-16のコード単位数、配列のCountは要素数であり、fileのbyte数とは異なります。

TotalCount・Tail・ReadCountを用途で選ぶ

先頭だけを確認

Get-Content -LiteralPath 'C:\Logs\app.log' -TotalCount 20

LiteralPathは角括弧などをwildcardとして解釈しません。先頭20行で形式と文字化けの有無を確認します。ただし、TotalCountはbyte数の上限ではないため、改行のない巨大fileでは先頭1行でも大量のmemoryを使うことがあります。

末尾と追記を監視

Get-Content -LiteralPath 'C:\Logs\app.log' -Tail 50 -Wait

-Waitはfileの追記を待ち続けるため、終了はCtrl+Cです。log rotation後の動作を実環境で確認し、長時間sessionの監視手段とは分けます。

一つの文字列として読む

$json = Get-Content -LiteralPath '.\settings.json' -Raw -Encoding utf8
$json | ConvertFrom-Json

-Rawは行配列ではなく単一文字列を返します。JSONは文字列分割せずConvertFrom-Jsonで解析します。ただし、解析成功だけでは設定に必要なキーや値の型まで検証できません。空の入力への対処は後述の例を参照してください。

大きなfileをstream処理

Get-Content -LiteralPath '.\access.log' -ReadCount 1000 |
  ForEach-Object { $_ | Select-String -SimpleMatch ' 500 ' }

この例のReadCount 1000は最大1000行ずつをpipelineへ渡し、ForEach-Objectの中で各行を検索します。byte数やmemory使用量を固定する指定ではなく、巨大な一行は分割されません。また、結果を変数へ全件保存するとその分のmemoryを使います。単純な検索ならSelect-Stringへpathを直接渡す方法もありますが、同じencodingを明示して比較します。特にWindows PowerShell 5.1ではBOMなしfileに対する両commandの既定encodingが異なります。

byteとして確認

Get-Content -LiteralPath '.\sample.bin' -AsByteStream -ReadCount 32 | Select-Object -First 1

-AsByteStreamはPowerShell 7系でbyteを読む用途です。binaryをtextとして表示せず、版のhelpでparameter有無を確認します。

PowerShell版によるencoding差を確認する

BOMがない場合、Windows PowerShell 5.1のGet-Contentは既定でシステムのANSIコードページを使い、PowerShell 7.xはUTF-8を使います。UTF-8と分かっているfileは -Encoding utf8 を明示します。読取時の指定はBOMを付けたり消したりする操作ではなく、BOMなしUTF-8も対象です。元の文字コードは作成元の仕様やbyte列と照合し、次の使い方を避けます。

  • 未知のlarge fileを全件読込する
  • PathとLiteralPathを混同する
  • encodingを端末の見た目だけで断定する
  • -Waitをservice監視の代替にする
  • JSONやCSVを文字列splitで解析する

機密logをconsoleへ出し過ぎない

読取commandでも、credentialやtokenを含むlogを画面・transcriptへ出すと漏えいになります。最小行だけをtestし、共有用copyでは承認済みmask処理を使います。出力redirectを入力と同じfileへ向けず、加工は別fileに保存します。変更が必要なら元fileのhashとACLを記録してcopyを作り、検証後に採用します。不合格ならcopyを破棄し元fileを保持します。

空fileと巨大一行をsampleで再現する

まずGet-ItemのLengthでbyte数を確認します。行objectの件数は Get-Content -LiteralPath … | Measure-Object のCountで確認できますが、全体を読むため大きなfileでは時間がかかります。Measure-Object -Lineによる文字列内の行数とは区別します。-Raw、通常読取、明示encodingの差は小さなsampleで比較し、先頭・末尾・既知行も確認します。読み取りだけなら原本は変更しません。以下の一時file作成や加工出力は原本と別pathへ限定します。

Count・Length・byte数で読取結果を確定する

Get-Contentは既定で行objectを返し、-Rawは一つのstring、-AsByteStreamはbyteを返します。-Tailだけなら末尾の指定行数を読み終えると終了し、-Waitを付けると追記を待ちます。更新中fileの読取は、一時点の整合したsnapshotを保証しません。読み取り成功、fileなし、文字化け、監視中rotationを分けて判定します。

Raw JSONを読み専用parserへ渡す

$raw = Get-Content -LiteralPath '.\settings.json' -Raw -Encoding utf8 -ErrorAction Stop
if ([string]::IsNullOrWhiteSpace($raw)) {
    throw 'settings.json は空、または空白のみです。'
}
$obj = ConvertFrom-Json -InputObject $raw -ErrorAction Stop
$type = if ($null -eq $obj) { '(null または出力なし)' } else { $obj.GetType().FullName }
[pscustomobject]@{ Chars = $raw.Length; Type = $type }

JSONのnullや、配列の列挙によって出力がなくなった場合に備え、GetTypeの前で $null を確認します。このTypeは代入後のPowerShellの型であり、JSONの最上位が配列かどうかの厳密な判定には使いません。PowerShell 7.xで最上位の配列を保持したい場合はConvertFrom-Jsonに -NoEnumerate を付けます。

空fileと読取失敗をLengthとErrorRecordで識別する

  • 期待型で読取成功:期待する型と件数で内容を取得し、-Rawなら改行を保った一つのstringになる
  • 空file:0byteのfileでは通常読取の出力は0件です。Rawの結果が $null か空stringかを区別し、文字列への変換後のLengthとfile sizeを併記します
  • 読取エラーとencoding不一致:path不存在、共有違反、権限不足など、commandが報告するエラーは -ErrorAction Stop とtry/catchで扱います。ただし、誤ったencodingでも文字化けした文字列が返り、エラーにならないことがあります。ErrorActionは文字コードを検証する指定ではありません

巨大fileを-ReadCount 0や-Rawで全量memoryへ載せず、行の長さも考慮してbatch sizeを決めます。巨大一行を固定サイズで読む必要がある場合は、別途byte単位で分割して処理する設計が必要です。-Waitには時間指定のtimeout引数はないため、Ctrl+Cや呼出側の停止管理を使います。-TotalCountとの併用では指定行数に達すると終了し、file削除でも待機が中断されます。log rotationの方式に応じて再接続を確認します。

BOM・改行・更新中logを境界にする

# 既存のempty.txtを上書きせず、一意な0byteの一時fileを作成する
$tempFile = [System.IO.Path]::GetTempFileName()
try {
    $lines = @(Get-Content -LiteralPath $tempFile -ErrorAction Stop)
    $raw = Get-Content -LiteralPath $tempFile -Raw -ErrorAction Stop
    [pscustomobject]@{
        Lines = $lines.Count
        RawIsNull = ($null -eq $raw)
        RawLength = ([string]$raw).Length
        Bytes = (Get-Item -LiteralPath $tempFile -ErrorAction Stop).Length
    }
}
finally {
    Remove-Item -LiteralPath $tempFile -ErrorAction Stop
}

この例は作成した一時fileだけをfinallyで削除します。Lines、RawLength、Bytesは0を期待し、RawIsNullでRawの戻り値も確認します。空、末尾改行あり/なし、CRLF、UTF-8 BOM有無、長い一行、更新中logは別々の小さなsampleでtestし、型、Count、Length、byte数、encoding、rotation時の再接続条件を記録します。

通常読取のCount、-RawのLength、Get-Itemのbyte数は同じ指標ではありません。期待する型を先に決め、empty fileや末尾改行なしでも判定が崩れないfixtureを残します。

公式情報・参考資料

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次