0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Where-Objectで条件抽出する――更新日時・拡張子・サイズでファイルを絞り込む

0
Last updated at Posted at 2026-07-11

この記事は以下のシリーズの18番目の記事です。

この記事でやること

この記事では、PowerShellの Where-Object を使って、条件に合うファイルだけを抽出する方法を整理します。

たとえば、次のような条件です。

条件
拡張子で絞る .txt だけ
ファイル名で絞る log を含むファイルだけ
サイズで絞る 10MB以上のファイルだけ
更新日時で絞る 30日以上更新されていないファイルだけ
複数条件で絞る .log かつ30日以上前のファイル

PowerShellでは、Get-ChildItem で対象を集め、Where-Object で条件に合うものだけを残す、という流れがよく使われます。

Get-ChildItem -File |
    Where-Object { $_.Extension -eq ".txt" }

まず結論

Where-Object の基本形は次の通りです。

Get-ChildItem -File |
    Where-Object { 条件 }

ファイル一覧を条件抽出するときは、次のように考えると分かりやすいです。

集める → 条件で絞る → 必要な項目だけ表示する

代表的な例です。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -eq ".log" } |
    Select-Object Name, FullName, LastWriteTime

これは、次の意味です。

配下のファイルを集める
拡張子が.logのものだけ残す
Name, FullName, LastWriteTimeだけ表示する

検証用フォルダを作る

まず、検証用フォルダを作成します。

New-Item -ItemType Directory -Path "C:\work\ps-where-test" -Force
Set-Location "C:\work\ps-where-test"

検証用ファイルを作成します。

Set-Content -Path ".\sample1.txt" -Value "text file 1"
Set-Content -Path ".\sample2.txt" -Value "text file 2"
Set-Content -Path ".\app.log" -Value "application log"
Set-Content -Path ".\error.log" -Value "error log"
Set-Content -Path ".\data.csv" -Value "id,name"

サイズ確認用に、少し大きめのファイルも作ります。

"1234567890" * 1000 | Set-Content -Path ".\large.txt"

サブフォルダも作成します。

New-Item -ItemType Directory -Path ".\sub" -Force
Set-Content -Path ".\sub\subsample.txt" -Value "sub folder text"
Set-Content -Path ".\sub\sublog.log" -Value "sub folder log"

確認します。

Get-ChildItem -Recurse

Where-Objectの基本形

Where-Object は、条件に合うものだけを残すコマンドです。

Get-ChildItem -File |
    Where-Object { $_.Extension -eq ".txt" }

$_ は、パイプラインで渡されてきた現在の1件を表します。

つまり、次の意味です。

現在処理中のファイルのExtensionが.txtなら残す

よく使うプロパティは次の通りです。

プロパティ 内容
Name ファイル名
FullName フルパス
Extension 拡張子
Length ファイルサイズ
CreationTime 作成日時
LastWriteTime 更新日時

確認したい場合は、まず Select-Object で表示すると分かりやすいです。

Get-ChildItem -File |
    Select-Object Name, Extension, Length, LastWriteTime

比較演算子の基本

Where-Object では、条件を書くために比較演算子を使います。

演算子 意味
-eq 等しい $_.Extension -eq ".txt"
-ne 等しくない $_.Extension -ne ".log"
-gt より大きい $_.Length -gt 1KB
-lt より小さい $_.Length -lt 1KB
-ge 以上 $_.Length -ge 1KB
-le 以下 $_.Length -le 1KB
-like ワイルドカード一致 $_.Name -like "*log*"
-notlike ワイルドカード不一致 $_.Name -notlike "*tmp*"
-match 正規表現一致 $_.Name -match "error"

PowerShellでは、比較演算子に = ではなく -eq などを使います。


拡張子で絞る

.txt ファイルだけを抽出します。

Get-ChildItem -File |
    Where-Object { $_.Extension -eq ".txt" }

サブフォルダも含める場合は、-Recurse を使います。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -eq ".txt" }

.log ファイルだけを抽出する場合です。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -eq ".log" }

拡張子が .log ではないものを抽出する場合です。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -ne ".log" }

ファイル名で絞る

ファイル名に log を含むものを抽出します。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Name -like "*log*" }

sample で始まるファイルを抽出します。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Name -like "sample*" }

error を含むファイルを抽出します。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Name -like "*error*" }

-like はワイルドカードを使う条件です。

条件 意味
"sample*" sampleで始まる
"*log*" logを含む
"*.txt" .txtで終わる

サイズで絞る

ファイルサイズは Length で確認できます。
Length はバイト単位です。

Get-ChildItem -File |
    Select-Object Name, Length

1KBより大きいファイルを抽出します。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Length -gt 1KB }

10MB以上のファイルを抽出する場合です。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Length -ge 10MB }

100MBより小さいファイルを抽出する場合です。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Length -lt 100MB }

表示するときは、MBに変換すると見やすくなります。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Length -ge 1KB } |
    Select-Object Name,
                  FullName,
                  @{Name="SizeKB"; Expression={[math]::Round($_.Length / 1KB, 2)}}

更新日時で絞る

更新日時は LastWriteTime で確認できます。

Get-ChildItem -File |
    Select-Object Name, LastWriteTime

30日以上更新されていないファイルを抽出する場合です。

Get-ChildItem -File -Recurse |
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) }

7日以内に更新されたファイルを抽出する場合です。

Get-ChildItem -File -Recurse |
    Where-Object { $_.LastWriteTime -ge (Get-Date).AddDays(-7) }

今日更新されたファイルを抽出する場合は、日付の境界を使うと分かりやすいです。

$today = (Get-Date).Date
$tomorrow = $today.AddDays(1)

Get-ChildItem -File -Recurse |
    Where-Object {
        $_.LastWriteTime -ge $today -and
        $_.LastWriteTime -lt $tomorrow
    }

作成日時で絞る

作成日時は CreationTime で確認できます。

Get-ChildItem -File |
    Select-Object Name, CreationTime

今月作成されたファイルを抽出する例です。

$firstDayOfThisMonth = Get-Date -Day 1 -Hour 0 -Minute 0 -Second 0

Get-ChildItem -File -Recurse |
    Where-Object { $_.CreationTime -ge $firstDayOfThisMonth }

前月以前に作成されたファイルを抽出する場合です。

$firstDayOfThisMonth = Get-Date -Day 1 -Hour 0 -Minute 0 -Second 0

Get-ChildItem -File -Recurse |
    Where-Object { $_.CreationTime -lt $firstDayOfThisMonth }

複数条件で絞る

複数条件を組み合わせる場合は、-and-or を使います。

演算子 意味
-and かつ
-or または
-not ではない

.log かつ30日以上更新されていないファイルを抽出します。

Get-ChildItem -File -Recurse |
    Where-Object {
        $_.Extension -eq ".log" -and
        $_.LastWriteTime -lt (Get-Date).AddDays(-30)
    }

.txt または .csv を抽出します。

Get-ChildItem -File -Recurse |
    Where-Object {
        $_.Extension -eq ".txt" -or
        $_.Extension -eq ".csv"
    }

名前に error を含み、かつサイズが1KBより大きいファイルを抽出します。

Get-ChildItem -File -Recurse |
    Where-Object {
        $_.Name -like "*error*" -and
        $_.Length -gt 1KB
    }

複数条件は、改行して書くと読みやすくなります。


配列に含まれるかで絞る

複数の拡張子を扱う場合は、配列と -in を使うと読みやすいです。

$extensions = @(".txt", ".csv", ".log")

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -in $extensions }

逆に、指定した拡張子以外を抽出する場合は -notin を使います。

$extensions = @(".tmp", ".bak")

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -notin $extensions }

条件が増える場合は、-or を何度も書くより、配列にした方が管理しやすいです。


条件抽出してCSVに出力する

Where-Object は、Export-Csv と組み合わせると実務で使いやすくなります。

30日以上更新されていないファイルをCSVに出力します。

Get-ChildItem -File -Recurse |
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
    Select-Object Name, FullName, Extension, Length, LastWriteTime |
    Export-Csv -Path ".\old_files.csv" -NoTypeInformation -Encoding UTF8

サイズをMB表示にしてCSV出力する場合です。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Length -ge 10MB } |
    Select-Object Name,
                  FullName,
                  Extension,
                  @{Name="SizeMB"; Expression={[math]::Round($_.Length / 1MB, 2)}},
                  LastWriteTime |
    Export-Csv -Path ".\large_files.csv" -NoTypeInformation -Encoding UTF8

削除や移動をする前に、まずCSVで一覧化して確認すると安全です。


削除前は必ず-WhatIfで確認する

条件抽出したファイルを削除することもできます。

ただし、いきなり削除するのは危険です。

悪い例です。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -eq ".log" } |
    Remove-Item

まずは -WhatIf を付けます。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -eq ".log" } |
    Remove-Item -WhatIf

-WhatIf を付けると、実際には削除せず、「何が削除対象になるか」を確認できます。

問題なければ、-WhatIf を外します。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -eq ".log" } |
    Remove-Item

条件抽出と削除を組み合わせる場合は、必ず事前確認する習慣をつけた方が安全です。


foreachと組み合わせる

条件抽出したファイルを1件ずつ処理したい場合は、foreach と組み合わせると分かりやすいです。

$files = Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -eq ".txt" }

foreach ($file in $files) {
    Write-Host "処理対象: $($file.FullName)"
}

コピーやログ出力など、1件ごとに複数行の処理をしたい場合は、foreach が扱いやすいです。

$backupDir = ".\backup"
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null

$files = Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -eq ".txt" }

foreach ($file in $files) {
    $destPath = Join-Path $backupDir $file.Name
    Copy-Item -Path $file.FullName -Destination $destPath -Force
}

実務で使いやすいテンプレート

条件に合うファイルを抽出してCSV出力するテンプレートです。

$targetDir = Join-Path $PSScriptRoot "target"
$outputDir = Join-Path $PSScriptRoot "output"

New-Item -ItemType Directory -Path $outputDir -Force | Out-Null

$today = Get-Date -Format "yyyyMMdd"
$outputPath = Join-Path $outputDir "filtered_files_$today.csv"

$extensions = @(".log", ".txt")

Get-ChildItem -Path $targetDir -File -Recurse |
    Where-Object {
        $_.Extension -in $extensions -and
        $_.LastWriteTime -lt (Get-Date).AddDays(-30)
    } |
    Select-Object Name,
                  FullName,
                  Extension,
                  @{Name="SizeMB"; Expression={[math]::Round($_.Length / 1MB, 2)}},
                  LastWriteTime |
    Export-Csv -Path $outputPath -NoTypeInformation -Encoding UTF8

このテンプレートでは、次の条件で抽出しています。

拡張子が.logまたは.txt
かつ
30日以上更新されていない

よくあるつまずき

= を使ってしまう

PowerShellの条件式では、等しいことを表すときに = ではなく -eq を使います。

悪い例です。

Where-Object { $_.Extension = ".txt" }

よい例です。

Where-Object { $_.Extension -eq ".txt" }

拡張子のドットを忘れる

Extension にはドットが含まれます。

$_.Extension -eq ".txt"

次のように .txt ではなく txt と書くと一致しません。

$_.Extension -eq "txt"

$_ の意味が分からなくなる

$_ は、現在処理している1件です。

Get-ChildItem -File |
    Where-Object { $_.Extension -eq ".txt" }

この場合、$_ は1つ1つのファイルを表します。


条件が長くなって読みにくい

複数条件は改行します。

Where-Object {
    $_.Extension -eq ".log" -and
    $_.LastWriteTime -lt (Get-Date).AddDays(-30)
}

削除対象を確認せずにRemove-Itemする

まず -WhatIf を付けます。

Get-ChildItem -File -Recurse |
    Where-Object { $_.Extension -eq ".log" } |
    Remove-Item -WhatIf

まとめ

この記事では、PowerShellの Where-Object で条件抽出する方法を整理しました。

基本形は次の通りです。

Get-ChildItem -File -Recurse |
    Where-Object { 条件 }

よく使う条件は次の通りです。

# 拡張子
$_.Extension -eq ".txt"

# ファイル名
$_.Name -like "*log*"

# サイズ
$_.Length -gt 10MB

# 更新日時
$_.LastWriteTime -lt (Get-Date).AddDays(-30)

# 複数条件
$_.Extension -eq ".log" -and $_.LastWriteTime -lt (Get-Date).AddDays(-30)

PowerShellで条件抽出するときは、次の流れで考えると分かりやすいです。

Get-ChildItemで集める
Where-Objectで絞る
Select-Objectで整える
Export-Csvで出力する

Where-Object を使えるようになると、古いファイルの洗い出し、大きいファイルの確認、特定拡張子の抽出、削除前の確認などが書きやすくなります。

削除や移動と組み合わせる場合は、必ず -WhatIf やCSV出力で対象を確認してから実行するのがおすすめです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?