2016-03-16 37 views
0

我正在運行更新一些變量的批處理文件,特別是%PATH%。我的環境有一個已知的錯誤,其中引用了%PATH%中的目錄,即批處理腳本在塊中處理變量的方式不同嗎?

PATH=c:\windows;...;"c:\program files\foo"\bin;c:\program files\... 

我有一個附加到PATH的腳本。當我做一個IF塊中,我得到一個錯誤,e.g:

IF "1"=="1" (
    SET "PATH=%PATH%;c:\foo" 
) 

給出了錯誤

\微軟在這個時候意外。

其中\Microsoft顯然是來自%PATH%中某個目錄的片段。

如果SET不在條件塊內,我不會收到錯誤。爲什麼是這樣?

編輯:這似乎與PATH還包含括號的事實有關。這裏的問題的一個更好的例子:

C:\temp>SET "FOO=C:\Program Files (x86)\;foo" 
C:\temp>ECHO %FOO% 
C:\Program Files (x86)\;foo 
C:\temp>IF "1"=="1" (ECHO %FOO%) 
\ was unexpected at this time. 
C:\temp>IF "1"=="1" ECHO %FOO% 
C:\Program Files (x86)\;foo 

所以我的問題是真的,爲什麼它打破,如果它在括號分隔塊?

回答

2

JosefZ properly identified the problem with ) in the path,但他建議刪除所有報價的解決方案並不安全。

PATH變量內的任何路徑可以包括;!&)和/或^,使用正常的%PATH%膨脹時所有這些可引起各種問題。

可能存在的一些路徑與&)等引述,以及與有問題的字符一些未引用的路徑,這樣既%PATH%"%PATH%"可能會失敗。

擴展PATH唯一有保證的安全方式是通過延遲擴展,但您希望新值能夠在ENDLOCAL中生存。該怎麼辦? 。 。 。
。 。 。 FOR/F,並通過代碼延遲擴展撥動救援:-)

if "1"=="1" (
    setlocal enableDelayedExpansion 
    for /f "eol=: delims=" %%P in ("!path!") do (
    endlocal 
    set "path=%%P;c:\foo" 
) 
) 

簡單化的執行路徑擴展的像set path=%path%;c:\foo
set "path=%path%;c:\foo"猖獗,但它是不是安全。總的來說,人們並沒有意識到PATH管理所涉及的微妙複雜性。

如果你曾經試圖修改中的批處理腳本可以被釋放到野外PATH變量,那麼你應該總是使用像我上面所示的一個安全的方法。

如果並且只有當路徑尚未存在時,如果要有條件地將路徑追加到PATH,問題就變得更加複雜。有關潛在問題的列表,請參見How to check if directory exists in %PATH%?,以及相當健全的解決方案。

0
SET "PATH=%PATH:"=%;c:\foo" 

應該解決的問題,因爲quoes無關

注意:如果路徑入口包含這可能不是真的「;」。在這種情況下,您應該將目錄重命名爲合理的。

0

只需在路徑變量設置中刪除外部引號即可。無論如何,它們都不是必需的。當然不是在這種情況下,你在那些引號內部使用了引號。引號應該在你的路徑變量中,而不是在整個事物之外。

SET PATH=%PATH%;c:\foo 

爲了進一步應該怎麼做,這裏的一些額外的例子來闡明......

SET PATH=%PATH%;C:\foo 
SET PATH=%PATH%;"C:\Some Folder With Spaces In It" 
SET PATH=%PATH%;"C:\Program Files\Foobar Inc Software" 

但從來沒有......

SET "PATH=%PATH%;SomePath" 
+0

保持使用'set「varName = varValue」'帶雙引號的語法模式(一般轉義規則);如果'varValue'包含需要轉義的字符,則使用帶引號的'「%varName%」'(或在某些情況下延遲擴展'!varName!'...) – JosefZ

+0

正確。如果其中包含引號,則不會在引號之外使用引號。 – ManoDestra

+0

但是你不能控制PATH中的內容。可能有值與不帶引號的值的組合。 – dbenham

0

你是正確的,這有更多的與PATH也包含括號相關的事實。下面的例子說明這個問題明確:

==> (set "varName=var"value(s) with"space(s) and"right parentheses"") 
with"space(s) and"right was unexpected at this time. 

==> (set varName=var"value(s) with"space(s) and"right parentheses") 
and"right parentheses" was unexpected at this time. 

==> 

讀答案How does the Windows Command Interpreter (CMD.EXE) parse scripts?的說明。卸下所有"雙引號正確的(調整)你path變量一次總是如下(檢查用戶變量path以及如果存在的話):

我能看到的唯一解決方案。需要重新啓動。

adjust path variable

+0

盲目刪除PATH中的所有引號是不安全的,因爲分號';'是路徑中的有效字符,並且它也是路徑分隔符。因此,任何包含';'的路徑必須在變量PATH中引用。 – dbenham