2011年7月17日日曜日

PowerShellでファイルをゴミ箱に削除する関数を作った。

最近、PowerShellを使っている。
サーバー管理というよりは、テキストファイルの結合・分割、QRコードの一括作成、PDFの結合なんかといったファイル管理にもっぱら活用している。
PowerShellは上記のような作業をかんたに定型化することができるし、.NET FrameWorkで機能を拡張することもできるので、いろいろと重宝している。

そんな便利なPowerShellさんだが、ファイルの削除でゴミ箱を利用することができない。
Remove-Itemでファイルを削除すると、ファイルが復元できなくなる。

しかし、特定のフォルダの集合の中にある、特定のファイル名を持ったファイルだけを選んで削除するなんてことは、エクスプローラーではなかなか難しい。というか不便だ。
というわけで、PowerShellでファイルをゴミ箱送りにするための関数をつくってみた。

ゴミ箱の扱いには「Microsoft.VisualBasic 名前空間」のFileSystemクラスを利用するようだ。
VB.NET互換用に用意されているのかな?
他に代替案が見つからなかったので、今回はこれを使うとしよう。
できたのが下のスクリプト。
拡張子「.ps1」のテキストファイルに保存して、PowerShellでファイルを読みこめば、関数が利用できるようになる。


function global:Dust-Shoot
{
    [CmdletBinding()]
    param (
        #パラメーターを設定。複数の型を許容する記述の仕方がわからない
        [Parameter(parametersetname="file", position=0)]
        [String] $Path,
        [Parameter(ParameterSetName="Array", position=0, ValueFromPipeline=$true)]
        $InputObject
    )

    process
    {
        #アセンブリを読み込む。
        Add-Type -AssemblyName Microsoft.VisualBasic

        #フォルダとファイルを削除する
        function DustToRecycle ($file)
        {
            #フォルダとファイルを判定。
            if (Test-Path $file -PathType Container)
            {
                [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory($file,
                    [Microsoft.VisualBasic.FileIO.UIOption]::OnlyErrorDialogs,
                    [Microsoft.VisualBasic.FileIO.RecycleOption]::SendToRecycleBin)
            }
            elseif (Test-Path $file -PathType Leaf)
            {
                [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($file,
                    [Microsoft.VisualBasic.FileIO.UIOption]::OnlyErrorDialogs,
                    [Microsoft.VisualBasic.FileIO.RecycleOption]::SendToRecycleBin)
            }
            Write-Host $file "をゴミ箱に転送しました。"
        }

        Switch ($PsCmdlet.ParameterSetName)
        {
            "file"
            {
                if (!(test-path -Path $Path))
                {
                    Write-Host $Path "は存在しません。"
                }
                else
                {
                    $fullpath = Convert-Path $Path
                    DustToRecycle $fullpath
                }
            }
            "Array"
            {
                #オブジェクトの型を判定。もう少しまともなやり方はあるのかな?
                if ($InputObject.GetType().Name -eq "Object[]")
                {
                    foreach ($i in $InputObject)
                    {
                        $fullpath = $i.fullname
                        DustToRecycle $fullpath
                    }
                }
                else
                {
                    $fullpath = $InputObject.FullName
                    DustToRecycle $fullpath
                }
            }
        }
    }
}
なんかパラメーターの設定がうまくいかなくて、変数の名前の指定が必須となってしまった。ここらへんはどうしたら良いかよくわからん。

PowerShell 2.0以降は、「高度な関数」という機能で、関数をコマンドレットみたいに動作させることができるらしい。上記のスクリプトも、この「高度な関数」機能を使っているので、パイプライン経由でファイルを削除することも可能だ。
たとえば、
gci ~/Desktop/* *.pdf -Recurse | dust-shoot
なんてコマンドで、デスクトップとサブフォルダ内のPDFファイルを一括削除できる。
このくらいならエクスプローラー使っても大して手間は変わらないけれど……。

[参考にしたWebサイト]
http://msdn.microsoft.com/ja-jp/library/microsoft.visualbasic.fileio.filesystem.aspx
http://codezine.jp/article/detail/4941

0 件のコメント:

コメントを投稿

人気の投稿