新しいオプションを追加して、-Exclude で指定したフォルダとそのサブフォルダを完全に検索から除外する機能を実装するカスタマイズ例を説明します。新しいオプションを -ExcludeWithSubdirectories と名付け、これを Get-ChildItem コマンドレットに組み込みます。

https://github.com/PowerShell/PowerShell/blob/master/src/Microsoft.PowerShell.Commands.Management/commands/management/GetChildrenCommand.cs

クラスの定義の更新

まず、CustomizedGetChildItem クラスに新しいパラメータ -ExcludeWithSubdirectories を追加し、その動作を定義します。このパラメータは、-Exclude パラメータが指定された場合にのみ意味を持ちます。

# CustomizedGetChildItemCmdlet.psm1
using namespace System.Management.Automation
using namespace System.IO

# Cmdletのカスタマイズ定義
[Cmdlet(VerbsCommon.Get, "ChildItem")]
Class CustomizedGetChildItem : Microsoft.PowerShell.Commands.GetChildItemCommand
{
    [Parameter(Mandatory = $false)]
    [ValidateNotNullOrEmpty()]
    [string[]] $Exclude

    [Parameter(Mandatory = $false)]
    [switch] $Recurse

    [Parameter(Mandatory = $false)]
    [switch] $Directory

    [Parameter(Mandatory = $false)]
    [switch] $ExcludeWithSubdirectories

    protected override void BeginProcessing()
    {
        base.BeginProcessing();
        if ($this.ExcludeWithSubdirectories -and $this.Exclude) {
            # Excludeに指定された各パスに対して、サブディレクトリも含めて除外するリストを作成
            $this.Exclude = $this.Exclude | ForEach-Object {
                $currentPath = $_
                $subDirs = Get-ChildItem -Path $_ -Recurse -Directory | Select-Object -ExpandProperty FullName
                $subDirs += $currentPath
                $subDirs
            }
        }
    }

    protected override void ProcessRecord()
    {
        if ($this.Directory) {
            $this.InputObject = Get-ChildItem -Path $this.Path -Directory -Recurse:$this.Recurse -Exclude $this.Exclude
        } else {
            $this.InputObject = Get-ChildItem -Path $this.Path -Recurse:$this.Recurse -Exclude $this.Exclude
        }

        foreach ($item in $this.InputObject) {
            Write-Output $item
        }
    }
}

Export-ModuleMember -Cmdlet CustomizedGetChildItem

解説

  1. 新しいパラメータの定義:
  2. BeginProcessing メソッドの拡張:
  3. ProcessRecord メソッドの変更:

使用例

このカスタマイズされたコマンドレットを使うと、-Exclude に指定したディレクトリ及びその全てのサブディレクトリが検索結果から除外されます。これにより、より精密なファイルシステム操作が可能になります。

再帰処理

Get-ChildItem コマンドレットに再帰的な除外機能を組み込みます。この関数は特定のフォルダとそのサブフォルダを除外しながらディレクトリ構造を再帰的に検索しています。同様のロジックをカスタム Cmdlet の実装に適用します。

カスタム Cmdlet の更新

# CustomizedGetChildItemCmdlet.psm1
using namespace System.Management.Automation
using namespace System.IO

# Cmdletのカスタマイズ定義
[Cmdlet(VerbsCommon.Get, "ChildItem")]
Class CustomizedGetChildItem : Microsoft.PowerShell.Commands.GetChildItemCommand
{
    [Parameter(Mandatory = $false)]
    [ValidateNotNullOrEmpty()]
    [string[]] $Exclude

    [Parameter(Mandatory = $false)]
    [switch] $Recurse

    [Parameter(Mandatory = $false)]
    [switch] $Directory

    [Parameter(Mandatory = $false)]
    [switch] $ExcludeWithSubdirectories

    # Cmdletの処理をオーバーライド
    protected override void ProcessRecord()
    {
        Get-Folders -Path $this.Path -ExcludeFolders $this.Exclude
    }

    # 再帰的なフォルダ取得関数を定義
    function Get-Folders {
        param(
            [string]$Path,
            [string[]]$ExcludeFolders
        )

        # 現在のディレクトリ内のフォルダを取得
        $folders = Get-ChildItem -Path $Path -Directory -Recurse:$this.Recurse -ErrorAction SilentlyContinue

        foreach ($folder in $folders) {
            # 除外するフォルダ名が含まれているかチェック
            if ($ExcludeFolders -notcontains $folder.Name) {
                # 除外フォルダではない場合、フォルダ情報を出力
                Write-Output $folder

                # `-Recurse` が指定されている場合、再帰的にこの関数を呼び出し
                if ($this.Recurse) {
                    Get-Folders -Path $folder.FullName -ExcludeFolders $ExcludeFolders
                }
            }
        }
    }
}

Export-ModuleMember -Cmdlet CustomizedGetChildItem

解説