アプリ資材をCSVで一覧化するPowershellツール

# 注意
まず、pwsh(ver 7.4)をインストールしていたとしても`Wine32`をインストールしたパソコンならもしかしたら使えるかもしれません。

私のMacbookはCPUがIntelなのでBootcampからWindows10インストールして検証してみようと思います。

今回のツールの中核をなすコマンドレットの`Get-ChildItem`は`[System.IO]`の`Directory CLass`を参照しているからです。(Windows10などでは.NetFramework を使っているので`[System.IO.Directory]`のクラスを呼びます。)

`ls`, `tee`, Ubuntu(`tree`) コマンド、MSDOS(`dir`)で十分という方は頭が痛くなるので読まないことをお勧めします。(実はWin10で`tree`コマンド使えました。Macユーザーはbrewインストールで使えるようになります)

また、バージョン管理ツール導入済みならこんなツールは不要かもしれません。

# ツール概要
アプリのバージョン管理がうまくできてない且つ、フォルダ内のバージョンがいっぱいありすぎて中身を一覧化したい方へ

資材がある親フォルダを指定するだけでCSVフォーマットのデータとして中身を一覧化するツールを即席で作りました。
# 詳細
```.md
# アプリ資材の親フォルダ内のバージョン毎のアイテムをCSVで取得します。
　引数１：親フォルダのフルパス　　　(-Directory)
　引数２：出力したいCSVのフルパス　(-CsvPath)

# アプリ資材のフォルダ構成の例
.
├──親フォルダ
│    └──バージョン１
│    │　　 ├──MySQL
│    │　　 │　 │　 └── db
│    │　　 │　 │　 ├── ac_user.sql
│    │　　 │　 │　 └── my_form.sql
│    │　　 │ 　└──custom.cnf
│    │　　 ├──index.php
│    │　　 ├──myform.php
│    │　　 ├──ajax.php
│    │　　 └──compose.yml
│    ├──バージョン２
│    ├──バージョン３
            ・
            ・
            ・
※手書きですがご容赦ください

# CSVのヘッダー情報
｜バージョン名｜権限｜最終更新日時｜名前｜フォルダ内JSON形式｜

# CSVのデータ例
"VerName","Mode","LastWriteTime","Name","Item"
"14.1.1","d------","2019/5/26", "PostgresSQL","{[]:{}}{}{}"
"14.1.1",-a------","2019/5/26", "新しいテキスト.txt",""

```
# ソース
以下が可読性をほぼ無視したソースコードです。
```AuditDirectory.ps1
function AuditDirectory([string]$Directory,[string]$CsvPath){
    write-host "Start:`t$(get-date -Format "yyyyMMdd hh:m:ss.fff")"
    $outFile=$CsvPath
    $varTmp=@()
    $data=@()
    $json=@()
    $varTmp=(get-childitem -Path $Directory |select-object Name)
    try{
        foreach($strTmp in $varTmp){
            $varTmp+=-join($Directory,'¥',$strTmp.'Name')
        }
        foreach($strPath in $varPath){
            $csv=get-childitem -Path $strPath | select-object 'VerName',Mode,LastWriteTime,Name | ConvertTo-Csv -NoTypeInformation
            [int]$len_tgt=0
            [int]$len_path=0
            [in]$len=0
            [string]$VerName="`n"
            [string[]]$varMode="`n"
            foreach($row in $csv){
                $col_1=($row -split ',')[0]
                if('' -eq $col_1){
                    [string]$Pattern=-join($Directory,'¥')
                    [string]$rawPath=-join('',$strPath,'')
                    $len_tgt=$Pattern.Length
                    $len_path=$rawPath.Length
                    $len=$len_path - $len_tgt
                    $VerName=$rawPath.Substring($rawpath.Length - $len)

                    [string]$strMode=($row -split ',')[1]
                    $varMode=$strMode -split '"'
                    [string]$strPattern=$varMode[1]
                    [string]$charPattern=$strPattern.Substring(0,1)

                    [string]$strName=($row -split ',')[3]
                    [string]$charName=($strName -split '"')[1]
                    $magoPath=join-path $strPath $charName
                    if ('d' -eq $charPattern){
                        $json=get-childitem -Path $magoPath -Recurse | select-object Mode,LastWriteTime,Name | ConvertTo-Json -Compress
                    }else{
                        $json=''
                    }
                    $data+=-join('"' ,$VerName ,'"' ,$row ,"," ,'"' ,$json ,'"')
                }
            }
        }
    add-content -Path $outFile -Value '"VerName","Mode","LastWriteTime","Name","Item"' 
    add-content -Path $outFile -Value $data 
    }catch{
        write-host $_.Exception.Message
    }finally{
        write-host "Finish:`t$(get-date -Format "yyyyMMdd hh:m:ss.fff")"
    }
}
#使い方
AuditDirectory -Directory "C:/Users/work" -CsvPath "C:/Users/test.csv"
```
CSVも孫のアイテムのJSON形式での出力もできてたので問題ないと思います。

※macbookにbootcampでwindows10をインストールした環境でのみ実証してません。

# 綺麗にする
正直、こんな汚いソースコードは仕事に使えないです。

特に、テキスト加工が難しくしすぎて意味がわからないです。

なので、もっと時間をかけてシンプルに何がしたいのか整理して書き直しました。

```simple.ps1
function AuditDirectory([string]$Directory, [string]$CsvPath){
    Write-Host "Start:`t$(Get-Date -Format "yyyyMMdd hh:m:ss.fff")"
    $outFile = $CsvPath
    $data = @()

    try{
        # 対象のディレクトリーの小アイテムを取得
        $items = Get-ChildItem -Path $Directory

        foreach($item in $items){
            if($item.PSIsContainer){
                # 小アイテムがディレクトリーの場合、recurseで全部Jsonとして取得する
                $json = Get-ChildItem -Path $item.FullName -Recurse | 
                        Select-Object Mode, LastWriteTime, Name | 
                        ConvertTo-Json -Compress
            }
            else{
                # ファイルの場合
                $json = ''
            }
            
            # 最終的なアウトプットの配列の整形
            $data += @{
                VerName = $Directory
                Mode = $item.Mode
                LastWriteTime = $item.LastWriteTime
                Name = $item.Name
                Item = $json
            }
        }

        # CSVに出力、NoHeaderオプションなしでヘッダーも出力
        $data | Export-Csv -Path $outFile -NoTypeInformation
    }
    catch{
        Write-Host $_.Exception.Message
    }
    finally{
        Write-Host "Finish:`t$(Get-Date -Format "yyyyMMdd hh:m:ss.fff")"
    }
}

# 使い方
AuditDirectory -Directory "C:/Users/work" -CsvPath "C:/Users/test.csv"
```
ディレクトリかどうか判断するための条件式が難しいテキスト抽出から１行でできるようになりました。

いまのところ、windows10をmacosのブートキャンプでインストールした環境でしか支えてません。

というのも、windowsのライセンスも実機も持っていないからです。