Dir 透過管道傳輸到 Set 中

Dir 透過管道傳輸到 Set 中

我正在嘗試製作一個程式來選擇文件名,然後將其通過管道傳輸到變數中。

我的嘗試:

Dir /B "C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1" | (set /p myVar= & set myVar)

使用後會發出

myVar:1.14.4

計劃是讓它進入並回顯命令,所以我這樣做了

@echo off
Dir /B "C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1" | (set /p myVar= & set myVar)
echo e %myVar%
cmd /k

但所發生的一切是

e

我究竟做錯了什麼?另外,有沒有辦法用 FOR 來做到這一點?

答案1

我究竟做錯了什麼?

很簡單 - 您正在嘗試使用無法工作的技術;-) 由於 Windows 管道的工作方式,因此不可能使用管道命令輸出在父環境中設定環境變數。

您的腳本正在命令進程中運行 - 我們稱之為父進程。

Windows 管道啟動兩個子命令進程,每個進程都有自己獨立的環境空間。管道的左側在第一個子級中執行,右側在第二個子級中執行。管道將第一個子級的輸出作為第二個子級的輸入發送。成功SET /P在子進程中定義了新的 myVar 變量,並且SET MYVAR命令顯示該值。偉大的。

但隨後管道結束,兩個子進程都終止,它們關聯的環境消失。無法將 myVar 環境值從子管道程序傳回父環境。

Windows 管道設計有許多令人驚訝的副作用,讓那些不完全理解其機制的人感到困惑。看https://stackoverflow.com/q/8192318/1012053了解更多。我建議閱讀問題和所有答案。

有沒有辦法用 FOR 做到這一點?

是的,在環境變數中捕捉命令輸出的正確方法是透過 FOR,特別FOR /F是 DavidPostill 所示。雖然他的程式碼有一個確定的問題,一個潛在的問題,一個低效率的地方。

USEBACKQ處理命令的輸出時不需要使用。使用常規單引號'比反引號更簡單:for /f %%F in ('yourCommand') do ...

錯誤是echo myVar:%myVar%在 FOR 迴圈體內使用了 。這將顯示運行循環之前存在的值,myVar因為解析該行時會發生百分比擴展,並且整個 FOR 循環將一步解析。您需要啟用延遲擴充 ( setlocal enableDelayedExpansion),然後使用echo !myVar!檢視循環內設定的值。

可能會出現另一個問題 - FOR /F 會將值解析為空格分隔的標記,並且僅捕獲第一個標記。如果檔案名稱包含空格,則除非使用 DELIMS 選項指定無分隔符,否則您將無法取得完整名稱。

for /f "delims=" %%F in (....) do .... 

但沒有必要使用DIR /Band FOR /F。您可以簡單地使用普通FOR循環而不使用該/F選項。

例如,以下將簡單列出所有文件:

for %%F in ("C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1\*") do echo %%~nxF

指定~nx僅使用檔案名稱和副檔名,放棄磁碟機和資料夾路徑。

通常不需要使用環境變數 - 只需%%F在迴圈中使用 FOR 變數即可完成工作。

但是如果因為某些原因你確實需要循環之外的值,你當然可以這樣做

for %%F in ("C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1\*") do set "myVar=%%~nxF"

但這只會捕獲迭代的最後一個檔案。 myVar 變數將在每次迭代時被覆蓋。您的原始設計將捕獲列出的第一個文件(假設它可以工作)。除非您知道 Van1 資料夾僅包含一個文件,否則這似乎都不是一個好主意。

如果您需要將所有檔案捕獲到變數中,那麼您需要使用偽數組。 Batch 沒有正式的陣列概念,但可以輕鬆模擬。如果您只需在網上搜尋“批次檔數組”,您就可以找到大量範例

相關內容