【PowerShell】ファイル・フォルダ操作|Test-Path・New-Item・Copy-Item・Get-ChildItem

【PowerShell】ファイル・フォルダ操作|Test-Path・New-Item・Copy-Item・Get-ChildItem PowerShell

PowerShellでスクリプトを書くと、ファイルやフォルダの操作は必ず登場します。存在を確認するTest-Path、一覧を取るGet-ChildItem、作成するNew-Item、コピーや移動のCopy-ItemMove-Item、削除のRemove-Itemが基本セットです。

使い方は素直ですが、知っておくと便利な点がいくつかあります。Test-Pathファイルとフォルダを区別する方法、New-Item親フォルダがないと失敗することとその回避、Get-ChildItem再帰やフィルタです。この記事では、実機で確認しながら、ファイル操作の基本を整理します。

先に結論

  • 存在確認はTest-Path-PathType Leaf(ファイル)/Container(フォルダ)で種類も判定できます。
  • 一覧はGet-ChildItem-Recurseで再帰、-Filterで絞り込み、-File/-Directoryで種類を限定できます。
  • 作成はNew-Item -ItemType FileDirectory親フォルダがないと失敗するので、その場合は-Forceを付けます。
  • コピーはCopy-Item、移動はMove-Item。フォルダごとなら-Recurseです。
  • 削除のRemove-Item -Recurse -Forceは強力で取り消せません。慎重に使います。
  • パスの組み立てはJoin-Path、分解はSplit-Pathを使うと安全です。

ファイルの読み書きと文字コードは文字化けを直す方法、操作の失敗に備えるtry-catchでエラー処理、複数ファイルの処理に使うループ完全ガイドもあわせて参考になります。

スポンサーリンク

ファイル・フォルダの存在を確認する(Test-Path)

パスが存在するかどうかはTest-Pathで調べます。$true$falseが返るので、ifと組み合わせて使います。-PathTypeを付けると、ファイルなのかフォルダなのかも判定できます。

test-path.ps1
# 存在するか(ファイル・フォルダどちらでも True)
Test-Path "C:\work\data.txt"        # True / False

# 種類まで判定する
Test-Path "C:\work\data.txt" -PathType Leaf       # ファイルなら True
Test-Path "C:\work" -PathType Container            # フォルダなら True

# if と組み合わせる
if (Test-Path "C:\work\config.json") {
    Write-Host "設定ファイルがあります"
}

実機でも、ファイルに対してTest-Path -PathType LeafTrue-PathType ContainerFalseになりました。-PathTypeを付けないと、ファイルでもフォルダでも存在すればTrueになります。「フォルダがあるか」を厳密に確かめたいときは-PathType Containerを使います。

一覧を取得する(Get-ChildItem)

フォルダの中身を一覧するのがGet-ChildItemです(エイリアスはlsdir)。再帰やフィルタ、種類の限定など、オプションが充実しています。

get-childitem.ps1
# フォルダ直下の一覧
Get-ChildItem "C:\work"

# サブフォルダまで再帰的に
Get-ChildItem "C:\work" -Recurse

# 拡張子で絞り込む(-Filter は高速)
Get-ChildItem "C:\work" -Filter "*.log" -Recurse

# ファイルだけ / フォルダだけ
Get-ChildItem "C:\work" -File        # ファイルのみ
Get-ChildItem "C:\work" -Directory   # フォルダのみ

# 隠しファイルも含める
Get-ChildItem "C:\work" -Force

実機でも、-Recurse -Filter "*.log"でサブフォルダ内の.logファイルを取得でき、-Directoryでフォルダだけ、-Fileでファイルだけに絞れました。取得した各項目は、.Name(名前)、.FullName(フルパス)、.Length(サイズ)、.LastWriteTime(更新日時)などのプロパティを持つオブジェクトです。

get-childitem-props.ps1
# 各ファイルのプロパティを使う
Get-ChildItem "C:\work" -File | ForEach-Object {
    Write-Host "$($_.Name) : $($_.Length) バイト : $($_.LastWriteTime)"
}

# 名前(フルパス)だけ取り出す
Get-ChildItem "C:\work" -Filter "*.txt" |
    Select-Object -ExpandProperty FullName

一覧をWhere-Objectで絞り込んだりSort-Objectで並べ替えたりすると、より柔軟に扱えます。詳しくはWhere-Object・Select-Object・Sort-Objectを参照してください。

ファイル・フォルダを作成する(New-Item)

新しいファイルやフォルダを作るにはNew-Itemを使い、-ItemTypeFileDirectoryを指定します。ここに、つまずきやすい落とし穴があります。

new-item.ps1
# 空ファイルを作る
New-Item -Path "C:\work\new.txt" -ItemType File

# フォルダを作る
New-Item -Path "C:\work\logs" -ItemType Directory

# 中身付きで作りたいときは Set-Content / Out-File
Set-Content "C:\work\memo.txt" "メモの内容" -Encoding UTF8
親フォルダがないとNew-Itemは失敗する

実機で確認したところ、C:\work\x\y\z\deep.txtのように途中のフォルダ(x\y\z)が存在しない状態でNew-Itemを実行すると、失敗しました。途中のフォルダごと作りたいときは、-Forceを付けてください。-Forceを付けると、存在しない親フォルダを自動的に作成します。

new-item-force.ps1
# NG: 親フォルダ x\y\z が無いと失敗する
# New-Item -Path "C:\work\x\y\z\deep.txt" -ItemType File

# OK: -Force で親フォルダごと作成する
New-Item -Path "C:\work\x\y\z\deep.txt" -ItemType File -Force

# フォルダだけを階層ごと作る場合も -Force(または親から順に作る)
New-Item -Path "C:\work\2026\03\09" -ItemType Directory -Force

存在チェックしてから作成する(定番パターン)

「フォルダが無ければ作る」という処理は頻出します。Test-Pathで確認してからNew-Itemするのが定番です。すでにある場合にNew-Itemでエラーにしたくないときに役立ちます。

check-then-create.ps1
$logDir = "C:\work\logs"

# 無ければ作る
if (-not (Test-Path $logDir)) {
    New-Item -Path $logDir -ItemType Directory | Out-Null
    Write-Host "フォルダを作成しました"
}

# ログファイルに追記する(フォルダがある前提)
$logFile = Join-Path $logDir "app.log"
Add-Content -Path $logFile -Value "$(Get-Date) 処理開始" -Encoding UTF8

| Out-Nullを付けているのは、New-Itemが作成したオブジェクトを画面に出さないためです。日付を使ったログ出力はGet-Dateで日付をフォーマットする方法もあわせて使うと便利です。

コピー・移動する(Copy-Item / Move-Item)

コピーはCopy-Item、移動(名前変更も含む)はMove-Itemです。フォルダを中身ごと扱うときは-Recurse、既存を上書きするときは-Forceを付けます。

copy-move.ps1
# ファイルをコピー
Copy-Item "C:\work\a.txt" "C:\work\a_backup.txt"

# フォルダを中身ごとコピー
Copy-Item "C:\work\logs" "C:\backup\logs" -Recurse

# 既存ファイルを上書きしてコピー
Copy-Item "C:\work\a.txt" "C:\backup\a.txt" -Force

# 移動(名前の変更にも使える)
Move-Item "C:\work\old.txt" "C:\work\new.txt" 

実機でも、Copy-Itemでコピー先が作られ、Move-Itemでは元ファイルが消えて移動先にだけ残ることを確認しました。名前を変えるだけならMove-Itemを使います(専用のRename-Itemもあります)。

削除する(Remove-Item)※慎重に

削除はRemove-Itemです。フォルダを中身ごと消すには-Recurse、確認なしで消すには-Forceを付けます。ただし、この操作は取り消せません。特に-Recurse -Forceは強力なので、慎重に扱います。

remove-item.ps1
# ファイルを削除
Remove-Item "C:\work\temp.txt"

# 実行前に何が消えるか確認する(-WhatIf)
Remove-Item "C:\work\logs" -Recurse -WhatIf
# 「削除されます」という表示だけで、実際には消えない

# フォルダを中身ごと削除(取り消せないので注意)
Remove-Item "C:\work\logs" -Recurse -Force

# 安全策: 存在を確認し、対象を限定してから消す
$target = "C:\work\old_logs"
if (Test-Path $target -PathType Container) {
    Remove-Item $target -Recurse -Force
}
-WhatIf で消える対象を先に確認する

Remove-Itemは元に戻せません。削除スクリプトを作るときは、まず-WhatIfを付けて「何が削除されるか」を表示だけさせ、対象が正しいことを確認してから本実行してください。パスを変数で組み立てる場合は、変数が空($null)になっていないかも確認します。空のパスに-Recurse -Forceを付けると、意図しない範囲を消す事故につながります。

パスを組み立てる・分解する(Join-Path / Split-Path)

パスを文字列の+でつなぐと、区切りの\を二重に入れたり入れ忘れたりしがちです。Join-Pathを使うと、区切りを正しく処理してくれます。逆にパスを分解するのがSplit-Pathです。

join-split-path.ps1
# パスを組み立てる(区切りは自動で付く)
Join-Path "C:\data" "report.txt"     # C:\data\report.txt
Join-Path $logDir "app.log"           # 変数同士も安全につなげる

# パスを分解する
Split-Path "C:\data\report.txt" -Leaf     # report.txt(ファイル名)
Split-Path "C:\data\report.txt" -Parent   # C:\data(フォルダ部分)

# スクリプト自身の場所を基準にパスを作る(よく使う)
$here = Split-Path $MyInvocation.MyCommand.Path -Parent
$config = Join-Path $here "config.json" 

実機でも、Split-Path -Leafはファイル名report.txt-Parentはフォルダ部分C:\dataを返し、Join-Pathは区切りを正しく入れてC:\data\report.txtを作りました。スクリプトと同じフォルダにある設定ファイルを読むときなど、Join-PathSplit-Pathの組み合わせが役立ちます。

よくある失敗

New-Itemが親フォルダなしで失敗する

途中のフォルダが無いとNew-Itemは失敗します。階層ごと作りたいときは-Forceを付けます。

Test-Pathでファイルとフォルダを区別しない

-PathTypeを付けないと、ファイルでもフォルダでも存在すればTrueです。種類まで確かめたいなら-PathType LeafContainerを使います。

Remove-Itemを確認せず実行する

削除は取り消せません。まず-WhatIfで対象を確認し、パス変数が空でないかもチェックしてから実行します。

パスを+でつないで区切りを間違える

文字列の+\の付け忘れや二重付けが起きます。Join-Pathを使えば区切りを正しく処理できます。

Get-ChildItemの結果を再帰なしで探す

サブフォルダの中も探したいなら-Recurseを付けます。付けないと直下しか見ません。

よくある質問

Qフォルダが無ければ作る、はどう書きますか?
Aif (-not (Test-Path $dir)) { New-Item -Path $dir -ItemType Directory }が定番です。あるいはNew-Item -Path $dir -ItemType Directory -Forceでも、すでにある場合はエラーにならず通せます。
Qサブフォルダの中まで一覧するには?
AGet-ChildItem -Recurseを使います。拡張子で絞るなら-Filter "*.txt" -Recurse、ファイルだけなら-File、フォルダだけなら-Directoryを組み合わせます。
QTest-Pathでファイルとフォルダを区別するには?
A-PathType Leafでファイル、-PathType Containerでフォルダを判定します。指定しなければ、どちらでも存在すればTrueになります。
Q削除を安全に行うには?
AまずRemove-Item -WhatIfで「何が消えるか」を表示だけさせ、対象を確認してから本実行します。パスを変数で作る場合は、空でないかも必ずチェックしてください。-Recurse -Forceは取り消せないため特に慎重に扱います。
Qパスを安全に組み立てるには?
AJoin-Path "C:\data" "file.txt"を使うと、区切りの\を正しく処理してくれます。文字列の+でつなぐより、付け忘れや二重付けを防げます。

まとめ

  • 存在確認はTest-Path-PathType LeafContainerで種類も判定します。
  • 一覧はGet-ChildItem-Recurse-Filter-File-Directoryを使い分けます。
  • 作成はNew-Item親フォルダが無いと失敗するので、必要なら-Forceを付けます。
  • コピーはCopy-Item、移動はMove-Item。フォルダごとなら-Recurseです。
  • 削除のRemove-Itemは取り消せません。-WhatIfで先に確認します。
  • パスはJoin-Pathで組み立て、Split-Pathで分解すると安全です。

ファイル操作は、Test-Pathで確かめてから動く、New-Itemの親フォルダに気をつける、Remove-Item-WhatIfで確認する、という3つの習慣を持つと安全です。基本コマンドを組み合わせれば、バックアップや整理のスクリプトをすぐ書けるようになります。