手上有個需求,PowerShell 腳本接收檔案路徑參數,參數可為一到多筆,可以是明確路徑也可以包含萬用字元(Wildcard,即星號「*」),甚至要支援用 ~ 代表使用者 Home 目錄(C:\Users\username) 例如:

ShowLastWriteTime.ps1 D:\test1.txt D:\test2.gif
ShowLastWriteTime.ps1 ~\Documents\*.docx
ShowLastWriteTime.ps1 .\*.txt D:\Lab\*.txt X:\Logs\*\2021-08-*.txt

若純用 C# 思維實現以上功能,我會寫段邏輯檢查參數字串,若字串為明確路徑時直接讀取,若有 ~ 用 $Env:UserProfile 取代,遇到萬用字元時改呼叫 Get-ChildItem -Filter 比對。不過,PowerShell 比想像有彈性,,例如:Get-Content、Get-Item、Get-ChildItem 在傳入路徑時,原本就認得 ~ 跟 *。例如:

Get-ChildItem 認得 ~\Documents\*\*.jpg 這種表示法:

Get-Item 一般常用來取得單一物件,但如果路徑包含 * ,便會傳回符合路徑的物件陣列,甚至可用字串陣列傳入多組路徑:

善用這些特性,我們能輕鬆做到前面說的需求,以下是顯示檔案修改日期的 Script 範例:(註:參數宣告的 ValueFromRemainingArguments 相當於 C# params 關鍵字 的效果,可將剩餘的一到多個參數視為陣列物件處理。)

param (
    [Parameter(Mandatory=$true,ValueFromRemainingArguments=$true)]
    [string[]]$paths
)
Get-Item $paths | ForEach-Object {
    return [PSCustomObject]@{
        Path = $_.FullName
        LastWriteTime = $_.LastAccessTime
    }
}

是不是很簡單呢?

【同場加映】

Get-Item/Get-ChildItem/Get-Content 這些 Cmdlet 除了處理檔案,其路徑參數適用所有 PowerShell 提供者,包含 Rigistry、Alias、Environment、FileSystem、Function、Variable... 等等。在路徑前方加上 HKCU:/HKLM: 可讀寫 Registry、加 Env: 可查環境變數,完整列表可用 Get-PSProvider 查詢或參考官方文件

因此,萬用字元路徑技巧也可用在 Registry、Variable 上,不過 PowerShell 不像 Linux 有 ** 可表示一到多層子目錄,如有需要可使用 Get-ChildItem -Recurse 再配合 Regular Expression 模擬:

Explaining how to use PowerShell to resolve one or multiple paths containing wildcard char.


Comments

Be the first to post a comment

Post a comment