Powershell備忘録（応用）

# 初めに
リストの操作やファイル入出力等，実際にpowershellによる処理方法を記録する。
~~ググったら出てくるものの備忘録~~
# スクリプトの実行を許可
Windows10では、powershellのスクリプトファイルの実行はデフォルトで許可されていない。
powershellを管理者権限で開き、以下の命令を実行する。
```powershell
Set-ExecutionPolicy RemoteSigned
```
# ファイルをUTF-8で保存
デフォルトで保存すると、UTF-16で保存される。
UTF-8で保存したいときに。
```powershell
[System.IO.File]::WriteAllLines($saveFname, $list_URL)
```
# ファイルのリネーム
フォルダ内のファイルを一括で変更したいときに
例として、フォルダ`DIR`内のmp3ファイルを一括リネームする。
```powershell
$items = Get-ChildItem -path "$DIR\*.mp3"

foreach($item in $items){
    $fname=$item.Name
    #Write-Host $DIR"  "$item
    #Write-Host "$DIR_$fname"
    $newName = "$DIR"+"_"+$fname
    Rename-Item -LiteralPath $item  -newname $newName
```
`Get-ChildItem`でフォルダ内のmp3ファイルを全て取得。
`$item.Name`でファイル名のみを取得（`$item`のみだと絶対パスが帰ってくる）、`$newName`に新しいファイル名を作成後、`Rename-Item`でファイル名を変更する。
　　`-LiteralPath`を付けることで、スペースの入ったファイル名も変更可能。
# ファイルの移動
フォルダ内のファイルを一括で移動したいときに
例として、フォルダ`DIR`内のmp3ファイルを`DIR2`に移動する。
```powershell
Move-Item -path .\DIR\*.mp3 -destination (Convert-Path .\DIR2)
```

# Start-process
powershellから別のプログラムを実行する。
メモ帳等のアプリを別ウィンドウで開くことが可能。
## PowershellからPowershellを実行する
以下の書き方でも実行できるが，同期実行になる（このスクリプトの処理が全て終わるるのを待つ）．
```powershell
.\other_script.ps1
```
非同期で行う場合，以下の書き方で実行できる．（別のPowershellウィンドウが開く）．
```powershell
Start-Process powershell.exe -ArgumentList  "-file .\other_script.ps1 "
```
`-wait`を使うと、`Start-Process`を同期で行う。
`-PassThru`を使うとプロセスIDを取得できる．
実行したアプリを消すとき等に利用できる．
```powershell
$pid = Start-Process powershell.exe -ArgumentList  "-file .\other_script.ps1 " -PassThru
#プロセスIDを取得
Write-Host $pid_knock.id
#別スクリプトの停止Stop-Process -Id $pid.id
```

# リスト操作
## リストから任意の位置を削除・追加
リストを指定した位置で分割，要素を足すor消したのち結合することで実装．
```powershell
function addItem_FromList($arr,$index,$item){
    $arr_bef=$arr[0..$index]
    $arr_aft=$arr[($index+1)..$arr.Length]
    #$arr_bef[$arr.Length]=$item
    $arr_bef+=$item
    return $arr_bef+$arr_aft
}
function removeItem_FromList($arr,$index){
    $arr_bef=$arr[0..($index-1)]
    $arr_aft=$arr[($index+1)..$arr.Length]
    return $arr_bef+$arr_aft
}
```
# ログファイルを出力
日時付きでログをテキストに出力する．
`write-Output`と`Add-Content`でテキストファイルに追記できる．
1つ目の`write-Output`で日時を追記，2行目の`write-Output`でログを追記する．
```powershell
function writeLogFile($text){
    $LogFile="searchLog.txt"
    Write-Output (Get-Date -Format "yyyy/MM/dd HH:mm:ss") | Add-Content $LogFile -Encoding UTF8
    Write-Output $text | Add-Content $Name_LogFile -Encoding UTF8
}
```
# ファイル探索
## Get-ChildItemで特定のファイルを探索
```powershell
Get-ChildItem -filter A.txt -Recurse
```
-filterでマッチするファイル名を探索。`*`を使ってワイルドカードにできる。
`-Recurse`を使って再帰的に検索する。
## Get-ChildItemから特定のパスを含む結果を除外する
`Get-ChildItem`で取得したアイテムを`Where-Object`を使った正規表現ではじく．
`$_.FullName`でアイテムの絶対パスが取得，`-notmatch`によって一致しないアイテムを取得
```powershell
$dirs_exclude= ".*(node_modules|hogehoge|fuga\\fugafuga|\.mp4).*"
$fileItems=Get-ChildItem -Recurse -File  | Where-Object {$_.FullName -notmatch $dirs_exclude}
```


# ファイル出力（コンソール出力）
`Write-Host`だと出力されない。`Write-Output`だとリダイレクトされる。
`Write-Host`はコンソールへ出力されるため、パイプ処理に渡すことができず、ファイルへ出力できない。
参考：[Write-Host、Write-Output 、echo の使い分けはとても重要](https://tooljp.com/windows/chigai/html/Programming/Write_Host-Write_Output_echo-chigai.html)
```powershell
Write-Host "hello world from Host" > test.txt
Write-Output "hello world from Output" > test.txt
```