PowerShell でファイルやフォルダをごみ箱に入れる
Windows のごみ箱へ PowerShell から捨てるには次のようなコードを書きます。
$shell = New-Object -ComObject Shell.Application
$trash = $shell.NameSpace(10)
$trash.MoveHere("c:\untitled.txt")
ここで気を付けなければならないのは、ファイル名には相対パスは使えないということです。Convert-Path
などを用いて絶対パスで指定しなければなりません。もっと汎用的に使うには次のようなスクリプトを使います。
[CmdletBinding(SupportsShouldProcess = $True, DefaultParameterSetName = 'Path')]
Param (
[SupportsWildCards()]
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'Path',
ValueFromPipeline = $True,
ValueFromPipelineByPropertyName = $True
)]
[string[]]$Path,
[Alias('LP')]
[Alias('PSPath')]
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'LiteralPath',
ValueFromPipeline = $False,
ValueFromPipelineByPropertyName = $True
)]
[string[]]$LiteralPath
)
Begin {
$shell = New-Object -ComObject Shell.Application
$trash = $shell.NameSpace(10)
}
Process {
if ($PSBoundParameters.ContainsKey('Path')) {
$targets = Convert-Path $Path
} else {
$targets = Convert-Path -LiteralPath $LiteralPath
}
$targets | Foreach-Object {
if ($PSCmdlet.ShouldProcess($_)) {
$trash.MoveHere($_)
}
}
}
このコードを解説します。
[CmdletBinding(SupportsShouldProcess = $True, DefaultParameterSetName = 'Path')]
SupportsShouldProcess = $True
にすると、-WhatIf
-Confirm
などの引数が使えるようになります。
例えば先ほどのスクリプトを Remove-ToRecycleBin.ps1
という名前で保存した場合、Remove-ToRecycleBin * -Confirm
のように実行すると、次のように該当するファイルの一つ一つに対して本当に削除していいのかどうか確認プロンプトが表示されます。
PS> Remove-ToRecycleBin .\a.txt -Confirm
Confirm
Are you sure you want to perform this action?
Performing the operation "Remove-ToRecycleBin.ps1" on target "C:\Users\Zuishin\Desktop\a.txt".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): n
Confirm
Are you sure you want to perform this action?
Performing the operation "Remove-ToRecycleBin.ps1" on target "C:\Users\Zuishin\Desktop\b.txt".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
また、DefaultParameterSetName = 'Path'
はデフォルトのパラメータセットを Path
に指定しています。PowerShell はパラメータセットを用いて引数の組み合わせをオーバーロードすることができます。
参考: Use Parameter Sets to Simplify PowerShell Commands
Param (
[SupportsWildCards()]
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'Path',
ValueFromPipeline = $True,
ValueFromPipelineByPropertyName = $True
)]
[string[]]$Path,
[Alias('LP')]
[Alias('PSPath')]
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = 'LiteralPath',
ValueFromPipeline = $False,
ValueFromPipelineByPropertyName = $True
)]
[string[]]$LiteralPath
)
ここでは Path
と LiteralPath
の二つの引数を定義しています。Path
はワイルドカードを受け付けることを示すために SupportsWildCards
属性を付けます。自動的に展開されるわけではないので、実際の展開は自分で書く必要があります。
Mandatory = $True
はこの引数が必須であることを示します。必須の引数が指定されなかった場合、それを入力するためのプロンプトが表示されます。
Position = 0
はこの引数が最初の引数であることを示します。Remove-ToRecycleBin a.txt
のように実行した場合、-Path
をつけなくてもデフォルトのパラメータセットである Path
パラメータセットの最初の引数である $Path
の指定と推論されます。
パイプラインから引数を受け取るには二種類の受け取り方があります。Path
は ValueFromPipeline = $True
になっているので、入力されたデータがそのまま $Path
に代入されます。
一方、LiteralPath
は ValueFromPipeline = $False
になっているので入力されたデータをそのまま受け取ることはできませんが、ValueFromPipelineByPropertyName = $True
になっています。このため、入力されたデータに LiteralPath
というプロパティがあった場合、そのプロパティの内容が $LiteralPath
に代入されます。
また、LiteralPath
は LP
PSPath
の二つのエイリアスを持っています。このため、-LiteralPath a.txt
の代わりに -LP a.txt
と書くことができます。そして、Get-ChildItem
などの出力は PSPath
プロパティを持っていて、そこにファイルのフルパスが入っています。そのため、Get-ChildItem | Remove-ToRecycleBin
のようにパイプを使って入力することが可能です。
Begin {
$shell = New-Object -ComObject Shell.Application
$trash = $shell.NameSpace(10)
}
Begin
ブロックで COM オブジェクトである Shell.Application
と、ごみ箱を表す $trash
を作っています。
if ($PSBoundParameters.ContainsKey('Path')) {
$targets = Convert-Path $Path
} else {
$targets = Convert-Path -LiteralPath $LiteralPath
}
引数 Path
が指定されている時は、$targets
にはワイルドカードを展開してフルパスに直したものを入れます。また LiteralPath
が指定されている時は、$targets
にはワイルドカードを展開せずフルパスに直したものを入れます。
$targets | Foreach-Object {
if ($PSCmdlet.ShouldProcess($_)) {
$trash.MoveHere($_)
}
}
$targets
の各要素に対して $trash.MoveHere
を適用していますが、$PSCmdlet.ShouldProcess
判定をすることにより、削除を実行すべきでないファイルを残すようにしています。
執筆日: 2019/03/02
Discussion