この記事でやること
VBSでは、ファイルやフォルダを操作するために FileSystemObject をよく使います。
たとえば、次のような処理です。
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists("C:\work\sample.txt") Then
WScript.Echo "ファイルがあります"
End If
fso.CopyFile "C:\work\sample.txt", "C:\work\backup\sample.txt"
PowerShellでは、FileSystemObjectを使わなくても、標準コマンドでファイル操作ができます。
この記事では、VBSのFileSystemObjectでよく使う処理を、PowerShellではどのように書くかを整理します。
まず結論
VBSのFileSystemObjectは、PowerShellでは主に次のコマンドに置き換えられます。
| VBS FileSystemObject | PowerShell |
|---|---|
| FileExists | Test-Path |
| FolderExists | Test-Path |
| CreateFolder | New-Item -ItemType Directory |
| CreateTextFile | New-Item / Set-Content |
| OpenTextFile | Get-Content / Set-Content / Add-Content |
| CopyFile | Copy-Item |
| CopyFolder | Copy-Item -Recurse |
| MoveFile | Move-Item |
| MoveFolder | Move-Item |
| DeleteFile | Remove-Item |
| DeleteFolder | Remove-Item -Recurse |
| GetFile | Get-Item |
| GetFolder | Get-Item |
| GetFolder.Files | Get-ChildItem -File |
| GetFolder.SubFolders | Get-ChildItem -Directory |
PowerShellでは、ファイルやフォルダを単なる文字列ではなく、オブジェクトとして扱えます。
たとえば、Get-ChildItem で取得したファイルには、次のような情報があります。
| プロパティ | 内容 |
|---|---|
| Name | ファイル名 |
| FullName | フルパス |
| Extension | 拡張子 |
| Length | サイズ |
| CreationTime | 作成日時 |
| LastWriteTime | 更新日時 |
この点が、VBSからPowerShellへ移行するときの大きな違いです。
検証用フォルダを作る
まず、検証用フォルダを作成します。
New-Item -ItemType Directory -Path "C:\work\ps-fso-test" -Force
Set-Location "C:\work\ps-fso-test"
検証用ファイルを作成します。
Set-Content -Path ".\sample.txt" -Value "FileSystemObject migration test" -Encoding UTF8
バックアップ用フォルダも作っておきます。
New-Item -ItemType Directory -Path ".\backup" -Force
確認します。
Get-ChildItem
FileExistsをTest-Pathに置き換える
VBSでは、ファイルの存在確認に FileExists を使います。
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists("C:\work\sample.txt") Then
WScript.Echo "ファイルがあります"
Else
WScript.Echo "ファイルがありません"
End If
PowerShellでは、Test-Path を使います。
if (Test-Path ".\sample.txt") {
Write-Host "ファイルがあります"
}
else {
Write-Host "ファイルがありません"
}
ただし、Test-Path はファイルにもフォルダにも使えます。
ファイルであることまで確認したい場合は、Get-Item と組み合わせます。
if ((Test-Path ".\sample.txt") -and ((Get-Item ".\sample.txt").PSIsContainer -eq $false)) {
Write-Host "ファイルです"
}
PowerShell 7では、次のように -PathType Leaf を使うと分かりやすいです。
if (Test-Path ".\sample.txt" -PathType Leaf) {
Write-Host "ファイルがあります"
}
FolderExistsをTest-Pathに置き換える
VBSでは、フォルダの存在確認に FolderExists を使います。
If fso.FolderExists("C:\work\backup") Then
WScript.Echo "フォルダがあります"
End If
PowerShellでは、同じく Test-Path を使います。
if (Test-Path ".\backup") {
Write-Host "フォルダがあります"
}
フォルダであることまで確認したい場合は、PowerShell 7なら -PathType Container を使えます。
if (Test-Path ".\backup" -PathType Container) {
Write-Host "フォルダがあります"
}
Windows PowerShell 5.1でも、通常の存在確認であれば Test-Path で十分なことが多いです。
CreateFolderをNew-Itemに置き換える
VBSでは、フォルダ作成に CreateFolder を使います。
fso.CreateFolder "C:\work\backup"
PowerShellでは、New-Item を使います。
New-Item -ItemType Directory -Path ".\backup" -Force
-Force を付けると、既にフォルダが存在していてもエラーになりにくくなります。
実務では、コピー先やログ出力先のフォルダを先に作ることが多いです。
$backupDir = ".\backup"
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
| Out-Null を付けると、フォルダ作成時の表示を抑制できます。
CreateTextFileをSet-Contentに置き換える
VBSでは、テキストファイル作成に CreateTextFile を使います。
Set file = fso.CreateTextFile("C:\work\log.txt", True)
file.WriteLine "処理開始"
file.Close
PowerShellでは、Set-Content を使うと簡単です。
Set-Content -Path ".\log.txt" -Value "処理開始" -Encoding UTF8
追記したい場合は、Add-Content を使います。
Add-Content -Path ".\log.txt" -Value "処理終了" -Encoding UTF8
使い分けは次の通りです。
| コマンド | 動き |
|---|---|
| Set-Content | 上書き |
| Add-Content | 追記 |
| Get-Content | 読み込み |
ログ出力では、基本的に Add-Content を使うことが多いです。
OpenTextFileをGet-Content / Set-Content / Add-Contentに置き換える
VBSでは、テキストファイルの読み書きに OpenTextFile を使います。
Set file = fso.OpenTextFile("C:\work\sample.txt", 1)
text = file.ReadAll
file.Close
PowerShellで読み込む場合は、Get-Content を使います。
$text = Get-Content -Path ".\sample.txt" -Encoding UTF8
1つの文字列としてまとめて読みたい場合は、-Raw を使います。
$text = Get-Content -Path ".\sample.txt" -Raw -Encoding UTF8
上書きする場合は Set-Content です。
Set-Content -Path ".\sample.txt" -Value "上書きしました" -Encoding UTF8
追記する場合は Add-Content です。
Add-Content -Path ".\sample.txt" -Value "追記しました" -Encoding UTF8
文字コード問題を避けるため、日本語を扱う場合は -Encoding を明示しておくと安全です。
CopyFileをCopy-Itemに置き換える
VBSでは、ファイルコピーに CopyFile を使います。
fso.CopyFile "C:\work\sample.txt", "C:\work\backup\sample.txt", True
PowerShellでは、Copy-Item を使います。
Copy-Item -Path ".\sample.txt" -Destination ".\backup\sample.txt" -Force
コピー先フォルダが存在しないと失敗します。
そのため、先にフォルダを作成します。
$backupDir = ".\backup"
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
Copy-Item -Path ".\sample.txt" -Destination (Join-Path $backupDir "sample.txt") -Force
実務では、このように New-Item と Copy-Item をセットで使うことが多いです。
CopyFolderをCopy-Item -Recurseに置き換える
VBSでは、フォルダコピーに CopyFolder を使います。
fso.CopyFolder "C:\work\data", "C:\work\backup\data", True
PowerShellでは、Copy-Item -Recurse を使います。
Copy-Item -Path ".\data" -Destination ".\backup\data" -Recurse -Force
検証用にフォルダを作って試します。
New-Item -ItemType Directory -Path ".\data" -Force | Out-Null
Set-Content -Path ".\data\a.txt" -Value "a" -Encoding UTF8
Set-Content -Path ".\data\b.txt" -Value "b" -Encoding UTF8
Copy-Item -Path ".\data" -Destination ".\backup\data" -Recurse -Force
確認します。
Get-ChildItem ".\backup\data" -Recurse
MoveFileをMove-Itemに置き換える
VBSでは、ファイル移動に MoveFile を使います。
fso.MoveFile "C:\work\sample.txt", "C:\work\backup\sample.txt"
PowerShellでは、Move-Item を使います。
Move-Item -Path ".\sample.txt" -Destination ".\backup\sample.txt" -Force
移動先フォルダが存在しないと失敗します。
先に作成しておくと安全です。
$destDir = ".\moved"
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
Move-Item -Path ".\backup\sample.txt" -Destination (Join-Path $destDir "sample.txt") -Force
ファイル名だけ変更したい場合は、Rename-Item を使います。
Rename-Item -Path ".\moved\sample.txt" -NewName "sample_renamed.txt"
移動とリネームは似ていますが、意味を分けて使うと読みやすくなります。
DeleteFileをRemove-Itemに置き換える
VBSでは、ファイル削除に DeleteFile を使います。
fso.DeleteFile "C:\work\sample.txt", True
PowerShellでは、Remove-Item を使います。
Remove-Item -Path ".\moved\sample_renamed.txt"
ただし、削除は危険な処理です。
まずは -WhatIf を付けて、削除対象を確認します。
Remove-Item -Path ".\moved\sample_renamed.txt" -WhatIf
複数ファイルを削除する場合も、最初は必ず -WhatIf で確認します。
Get-ChildItem -Path ".\" -File -Filter "*.log" |
Remove-Item -WhatIf
問題なければ、-WhatIf を外します。
Get-ChildItem -Path ".\" -File -Filter "*.log" |
Remove-Item
DeleteFolderをRemove-Item -Recurseに置き換える
VBSでは、フォルダ削除に DeleteFolder を使います。
fso.DeleteFolder "C:\work\data", True
PowerShellでは、Remove-Item -Recurse を使います。
Remove-Item -Path ".\data" -Recurse
ただし、フォルダ削除は影響が大きいため、まず -WhatIf で確認します。
Remove-Item -Path ".\data" -Recurse -WhatIf
読み取り専用ファイルなども含めて削除する場合は、-Force を使うことがあります。
Remove-Item -Path ".\data" -Recurse -Force
ただし、-Recurse -Force は強力です。
対象パスを必ず確認してから実行します。
GetFileをGet-Itemに置き換える
VBSでは、GetFile を使ってファイルオブジェクトを取得します。
Set file = fso.GetFile("C:\work\sample.txt")
WScript.Echo file.Name
WScript.Echo file.Size
WScript.Echo file.DateLastModified
PowerShellでは、Get-Item を使います。
$file = Get-Item ".\sample.txt"
Write-Host $file.Name
Write-Host $file.Length
Write-Host $file.LastWriteTime
PowerShellでは、取得したファイルにさまざまなプロパティがあります。
$file | Select-Object Name, FullName, Length, CreationTime, LastWriteTime
ファイルサイズは Length です。
バイト単位なので、MB表示にしたい場合は次のようにします。
[math]::Round($file.Length / 1MB, 2)
GetFolder.FilesをGet-ChildItem -Fileに置き換える
VBSでは、フォルダ内のファイル一覧を取得するために GetFolder(...).Files を使います。
Set folder = fso.GetFolder("C:\work")
For Each file In folder.Files
WScript.Echo file.Name
Next
PowerShellでは、Get-ChildItem -File を使います。
Get-ChildItem -Path "." -File
必要な項目だけ表示するなら、Select-Object を使います。
Get-ChildItem -Path "." -File |
Select-Object Name, FullName, Length, LastWriteTime
サブフォルダも含める場合は、-Recurse を付けます。
Get-ChildItem -Path "." -File -Recurse |
Select-Object Name, FullName, Length, LastWriteTime
PowerShellでは、この一覧をそのままCSVに出力できます。
Get-ChildItem -Path "." -File -Recurse |
Select-Object Name, FullName, Length, LastWriteTime |
Export-Csv -Path ".\file_list.csv" -NoTypeInformation -Encoding UTF8
GetFolder.SubFoldersをGet-ChildItem -Directoryに置き換える
VBSでは、サブフォルダ一覧に SubFolders を使います。
Set folder = fso.GetFolder("C:\work")
For Each subFolder In folder.SubFolders
WScript.Echo subFolder.Name
Next
PowerShellでは、Get-ChildItem -Directory を使います。
Get-ChildItem -Path "." -Directory
サブフォルダも含めて取得する場合は、-Recurse を付けます。
Get-ChildItem -Path "." -Directory -Recurse
必要な項目だけ表示します。
Get-ChildItem -Path "." -Directory -Recurse |
Select-Object Name, FullName, CreationTime, LastWriteTime
BuildPathはJoin-Pathに置き換える
VBSでは、パスを結合するために BuildPath を使うことがあります。
path = fso.BuildPath("C:\work", "sample.txt")
PowerShellでは、Join-Path を使います。
$path = Join-Path "C:\work" "sample.txt"
.ps1 と同じフォルダを基準にするなら、次のようにします。
$filePath = Join-Path $PSScriptRoot "sample.txt"
文字列を直接結合することもできます。
$filePath = $PSScriptRoot + "\sample.txt"
ただし、実務では Join-Path を使う方が安全で読みやすいです。
GetExtensionNameはExtensionに置き換える
VBSでは、拡張子を取得するために GetExtensionName を使います。
ext = fso.GetExtensionName("C:\work\sample.txt")
PowerShellでは、Get-Item や Get-ChildItem の Extension プロパティを使います。
$file = Get-Item ".\sample.txt"
$file.Extension
結果は .txt のようにドット付きで返ります。
複数ファイルの拡張子を表示します。
Get-ChildItem -File |
Select-Object Name, Extension
拡張子で絞る場合は、Where-Object を使います。
Get-ChildItem -File |
Where-Object { $_.Extension -eq ".txt" }
GetBaseNameはBaseNameに置き換える
VBSでは、拡張子を除いたファイル名を取得するために GetBaseName を使います。
baseName = fso.GetBaseName("C:\work\sample.txt")
PowerShellでは、BaseName プロパティを使います。
$file = Get-Item ".\sample.txt"
$file.BaseName
複数ファイルで確認する場合です。
Get-ChildItem -File |
Select-Object Name, BaseName, Extension
日付付きファイル名を作る場合にも使えます。
$file = Get-Item ".\sample.txt"
$today = Get-Date -Format "yyyyMMdd"
$newName = "$($file.BaseName)_$today$($file.Extension)"
Write-Host $newName
GetParentFolderNameはDirectoryNameに置き換える
VBSでは、親フォルダを取得するために GetParentFolderName を使います。
parent = fso.GetParentFolderName("C:\work\sample.txt")
PowerShellでは、DirectoryName を使います。
$file = Get-Item ".\sample.txt"
$file.DirectoryName
ファイル一覧で親フォルダを表示します。
Get-ChildItem -File -Recurse |
Select-Object Name, DirectoryName, FullName
共有フォルダ調査などでは、どのフォルダにファイルがあるかを確認するために便利です。
VBSとPowerShellの大きな違い
FileSystemObjectをPowerShellに置き換えるとき、単純にコマンド名を置き換えるだけでは不十分です。
大きな違いは、PowerShellがオブジェクトを扱うことです。
VBSでは、ファイルパスやファイル名を文字列として扱う場面が多くなります。
WScript.Echo file.Name
WScript.Echo file.Size
PowerShellでは、Get-ChildItem の結果にプロパティが含まれています。
Get-ChildItem -File |
Select-Object Name, FullName, Length, LastWriteTime
さらに、条件抽出や並べ替えもできます。
Get-ChildItem -File -Recurse |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
Sort-Object LastWriteTime |
Select-Object Name, FullName, LastWriteTime
このように、PowerShellでは次の流れで考えると分かりやすいです。
集める
絞る
並べる
選ぶ
出力する
実務で使いやすいテンプレート
FileSystemObject移行でよく使う処理をまとめたテンプレートです。
$baseDir = $PSScriptRoot
$inputDir = Join-Path $baseDir "input"
$backupDir = Join-Path $baseDir "backup"
$logDir = Join-Path $baseDir "logs"
New-Item -ItemType Directory -Path $inputDir -Force | Out-Null
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
$today = Get-Date -Format "yyyyMMdd"
$logPath = Join-Path $logDir "process_$today.log"
function Write-Log {
param(
[string]$Message,
[string]$Level = "INFO"
)
$now = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $logPath -Value "[$now][$Level] $Message" -Encoding UTF8
}
Write-Log "処理開始"
Write-Log "inputDir: $inputDir"
Write-Log "backupDir: $backupDir"
try {
$files = Get-ChildItem -Path $inputDir -File -Filter "*.txt" -ErrorAction Stop
Write-Log "対象ファイル数: $($files.Count)"
foreach ($file in $files) {
try {
$destPath = Join-Path $backupDir $file.Name
Copy-Item -Path $file.FullName -Destination $destPath -Force -ErrorAction Stop
Write-Log "コピー成功: $($file.FullName) -> $destPath"
}
catch {
Write-Log "コピー失敗: $($file.FullName) / $($_.Exception.Message)" "ERROR"
}
}
}
catch {
Write-Log "全体エラー: $($_.Exception.Message)" "ERROR"
}
finally {
Write-Log "処理終了"
}
このテンプレートでは、次の処理をしています。
スクリプト配置場所を基準にする
input / backup / logs フォルダを作る
input内の.txtファイルを取得する
backupへコピーする
処理結果をログに残す
VBSのFileSystemObjectでよくある「指定フォルダ内のファイルを処理する」パターンを、PowerShellらしい形に置き換えた例です。
よくあるつまずき
Test-Pathだけではファイルかフォルダか分からない
Test-Path は、ファイルにもフォルダにも使えます。
Test-Path ".\sample.txt"
ファイルかフォルダかを明確にしたい場合は、PowerShell 7では -PathType を使えます。
Test-Path ".\sample.txt" -PathType Leaf
Test-Path ".\backup" -PathType Container
コピー先フォルダを作っていない
Copy-Item は、コピー先フォルダがないと失敗します。
Copy-Item -Path ".\sample.txt" -Destination ".\backup\sample.txt"
先に作成します。
New-Item -ItemType Directory -Path ".\backup" -Force | Out-Null
削除処理をいきなり実行している
Remove-Item は強力です。
Remove-Item ".\*.log"
まずは -WhatIf を使います。
Get-ChildItem -File -Filter "*.log" |
Remove-Item -WhatIf
相対パスで実行場所がズレる
タスクスケジューラで実行すると、相対パスが想定外の場所を指すことがあります。
Copy-Item ".\sample.txt" ".\backup\sample.txt"
.ps1 と同じフォルダを基準にするなら、$PSScriptRoot を使います。
$sourcePath = Join-Path $PSScriptRoot "sample.txt"
$backupDir = Join-Path $PSScriptRoot "backup"
日本語ファイル名や特殊文字でうまく扱えない
通常は -Path で問題ありませんが、[ や ] など特殊文字を含むパスでは -LiteralPath を検討します。
Get-Content -LiteralPath ".\売上[2026].txt" -Encoding UTF8
まとめ
この記事では、VBSのFileSystemObjectをPowerShellに置き換える基本パターンを整理しました。
代表的な対応関係は次の通りです。
| VBS FileSystemObject | PowerShell |
|---|---|
| FileExists / FolderExists | Test-Path |
| CreateFolder | New-Item -ItemType Directory |
| CreateTextFile | Set-Content |
| OpenTextFile | Get-Content / Set-Content / Add-Content |
| CopyFile / CopyFolder | Copy-Item |
| MoveFile / MoveFolder | Move-Item |
| DeleteFile / DeleteFolder | Remove-Item |
| GetFile / GetFolder | Get-Item |
| Files / SubFolders | Get-ChildItem |
| BuildPath | Join-Path |
| GetExtensionName | Extension |
| GetBaseName | BaseName |
| GetParentFolderName | DirectoryName |
VBSからPowerShellへ移行するときは、FileSystemObjectのメソッドを1対1で置き換えるだけではなく、PowerShellの考え方に合わせることが重要です。
特に大事なのは、次の5つです。
パスはJoin-Pathで作る
スクリプト基準の場所は$PSScriptRootを使う
一覧取得はGet-ChildItemを使う
削除前は-WhatIfで確認する
処理結果はログに残す
PowerShellでは、ファイルやフォルダをオブジェクトとして扱えるため、VBSよりも条件抽出、並べ替え、CSV出力、ログ管理が書きやすくなります。
FileSystemObjectからPowerShellへ移行する目的は、単に古い文法を新しい文法に変えることではありません。
社内にある小さな自動化を、より安全に、より運用しやすい形に作り直すことです。