想將 "TIME:$(Get-Date -Format HH:mm)" | Add-Content "$(Get-Date -Format yyyyMMdd).txt" 當成 PowerShell.exe -Command 參數放在 .bat 檔執行,卡了老半天。

直接寫 powershell -Command "TIME:$(Get-Date -Format HH:mm)" | Add-Content "$(Get-Date -Format yyyyMMdd).txt" 會解析錯誤,CMD 會拆成 powershell Get-Date -Format HH:mm 串接 Add-Cotent ...,而 Add-Content 非有效 CMD 指令,會噴出「不是內部或外部命令錯誤、可執行的程式或批次檔」訊息。

前後加上雙引號當成字串參數傳入,原本的 " 依 CMD 慣例要跳脫成 "",依理會寫成 powershell -Command "& {""TIME:$(Get-Date -Format HH:mm)"" | Add-Content ""$(Get-Date -Format yyyyMMdd).txt""}",但卻得到「字串遺漏結尾字元:"」錯誤,胡亂將 "" 改成 PowerShell 內跳脫字元也不對:
註:寫成 Inline Script Block 時要加 & 參考

沒在官方文件查到相關說明,最後是在 Stackoverflow 查到一篇超詳細的批次檔雙引號跳脫大全,完整收錄在 CMD、Bash、PowerShell CLI 的雙引號處理方式。在 Calling PowerShell's CLI from cmd.exe or POSIX-like shells 一節提到:

  • "" 寫法在 CMD 或批次呼叫 Windows PowerShell 時會出現 字串遺漏結尾字元:" / error "The string is missing the terminator" 錯誤 (就是我遇到的狀況),但 PowerShell [Core] v6+ 沒問題。
  • \"""" 基本上可行,但不保險,像是遇到 & 時會解析錯誤,必須也改成 ^&
  • \"" 可以,但缺點是連續空白會被壓縮(類似 HTML 處理連續空白的行為):(# 到 Q&A 間的七個空白只算一個)
  • "^""(是,你沒看錯,要四個符號) 是 Windows PowerShell 的最佳解,PowerShell [Core] v7+ 則可用 ""
  • 若在 Unix-like 平台 (macOS、Linux),只能用 PowerShell Core - pwsh,請一律使用 \" 即可,或是最外層包字串的雙引號改用單引號:

題外話,為了要實測 Linux 跑 PowerShell v7,趁此機會試了在 Debian 上安裝 PowerShell,照著官方文件 在 Debian Linux 上安裝 PowerShell 不用一分鐘裝完,熟悉的 Get-Process 指令搬到 Linux 也能跑,看到的則是 Linux 上正在運行的程序,酷!

最後小試一下,載入 NuGet 程式庫(.NET Standard/.NET Core 版),在 Linux 要用 PowerShell 產生 QRCode 也是小菜一碟。
註:在 PowerShell 要引用巢狀類別,不是用 . ,而是要寫成 +,如下圖的 [Net.Codecrete.QrCodeGenerator.QrCode+Ecc]::Medium

未來在 Linux 除了 Bash,又多一個寫 Shell 腳本的選擇。

Tips of the correct way to escape double quotation marks when calling PowerShell in shell/batch.


Comments

Be the first to post a comment

Post a comment