2016-12-24 12 views
3

我遇到了一個問題,看起來它應該是一個相當基本的腳本。批量條件編程 - 不能將STDERR指定到NUL

ECHO !url1! >> !hostsfile! && ECHO Successfully added !url1! to file. || 2>&1>NUL && ECHO Unable to write !url1! to file. && GOTO :FAIL 

這是一個條件,試圖到URL寫入給定的文件,如果訪問該文件被拒絕,打印錯誤消息。不幸的是,CMD也會生成它自己的錯誤信息,所以目前作爲輸出,我得到了默認錯誤「拒絕訪問」,然後是我自己的「無法將www.url.com寫入文件」。

我試過沒有運氣將管道默認的錯誤消息給NUL,但即使所有我讀到它,我的知識如何管道工作和它的語法仍然稀疏,我不是到任何地方。

此外,作爲旁道:是否有任何方法可以將該行分割爲更易於管理而不會導致錯誤?

嘗試這樣的東西:

ECHO !url1! >> !hostsfile! && ECHO Successfully added !url1! to Hosts file. 
|| 2>&1>NUL && ECHO Unable to write !url1! to Hosts. && GOTO :FAIL 

ECHO !url1! >> !hostsfile! && ECHO Successfully added !url1! to Hosts file. || 
2>&1>NUL && ECHO Unable to write !url1! to Hosts. && GOTO :FAIL 

...導致 「意外字符」 的錯誤。

注:由於延遲擴展,感嘆號被用於變量。

+1

回聲不會返回錯誤級別[dbenhams廣泛的答案到錯誤級別問題](http://stackoverflow.com/a/34937706/6811411)並閱讀[ss64.com errorlevel](http:// ss64 .com/nt/errorlevel.html) – LotPings

+2

你應該用這種方式重定向'2>&1> Nul'或'2>&1 1> Nul'在標準數據流之間放置一個空格或明確標識數字1 – LotPings

+0

@LotPings - 我會在沒有'echo'的情況下完成我想要做的事情嗎?有沒有我可以用來檢查寫入權限的命令?有沒有一種方法可以使用'echo'來達到我想要的目的? – Hashim

回答

4

有幾個問題:

  1. 2>&1>NUL無效redirection syntax,你不能連接多個重定向操作符那樣。我想你想的STDERR流至nul設備重定向,所以應該讀2>nul2> nul
  2. 您只能重定向一個命令的輸入/輸出,因此不能在沒有任何命令的情況下使用重定向。您正嘗試(錯誤地)重定向2>&1>NUL,但沒有命令。
  3. echo命令實際上不產生錯誤信息Access is denied.,它是由一個失敗的重定向引起的。因此,必須將重定向的echo命令括在括號內,以便能夠通過2> nul重定向來抑制錯誤消息。
  4. 請注意,echo命令本身不會設置ErrorLevel僞變量,也不會設置退出代碼。然而,失敗的重定向(<>>>)將退出代碼,這就是你感興趣的內容。
  5. 您需要確保goto命令在||分支才執行,所以你應該把那整括號之間的部分。
  6. 當您編寫echo Text > file.ext時,SPACEText>之間也會輸出。爲了避免這種情況,或者簡單像echo Text>file.ext(echo Text) > file.ext刪除它,放置一對括號圍繞echo命令,或恢復的語法等> file.ext echo Text(這是我喜歡,因爲它是最普遍的一個方式)。
  7. 當您編寫echo Text & goto :LABEL時,輸出&之前的SPACE也非常類似。爲了避免這種情況,請將其刪除,或將括號內的echo部分括起來。
  8. 在你的進一步嘗試中,你不告訴cmd這兩條線屬於一起。通過以一個插入符號^結束一行來完成行連續,因此下一個連接。下一行應在前面(至少)SPACE。或者,括號內的代碼塊可能跨越多行,因此您也可以結束第一行,如... || (,並將下一行像...)一樣視爲單個命令行。

這裏是固定的代碼:

(>> "!hostsfile!" echo !url1!) 2> nul && (echo Successfully added !url1! to file.) || (echo Unable to write !url1! to file.& goto :FAIL) 

或(使用行繼續):

(>> "!hostsfile!" echo !url1!) 2> nul && (echo Successfully added !url1! to file.)^
    || ((echo Unable to write !url1! to file.) & goto :FAIL) 

或者甚至(使用parenthesised塊):

(>> "!hostsfile!" echo !url1!) 2> nul && (
    echo Successfully added !url1! to file. 
) || (
    echo Unable to write !url1! to file. 
    goto :FAIL 
) 

1)這兩個值幾乎總是相同的,但在極少數情況下它們是不同的; &&||運營商確實不關心ErrorLevel,他們寧願使用退出代碼。

2)的後插入符號^cmd忽略下一行斷逸出以下字符,因此兩條線echo A^& echo B導致輸出A& echo B作爲&出現轉義;要實現兩行輸出AB,請將第二行更改爲SPACE + & echo B,因此SPACE已轉義,但該&符號不是。

+0

絕大部分的答案。我應該指出,它實際上是觸發「訪問被拒絕」消息的「回聲」。如果您打開命令提示符而沒有升級並嘗試附加您的主機文件,那就是結果的錯誤。如果主機是attrib'd + s或+ r,我沒有測試是否會出現相同的錯誤,但我懷疑它確實發生了。仍然是+1。 – rojo

+0

謝謝,@rojo! 「沒有升級」是什麼意思?不確定它是否真的產生錯誤,因爲'2> nul>「!hostfile!」 echo text'顯示錯誤信息,只有'2> nul(>「!hostfile!」echo Text)'... – aschipfl

+0

「沒有升級」我的意思不是管理員。如果您運行的是Windows 10,則需要右鍵單擊開始菜單,然後選擇不會顯示「(Admin)」的命令提示符。我看到了@rojo, – rojo

0

我想嘗試這樣的事:

Set hostsfile=%Systemroot%\System32\drivers\etc\hosts 
Findstr /I "!url1!" "!hostsfile!" 2>&1 >NUL &&(Echo !hostsfile! already contains !url1! & goto :whereever) 
>> !hostsfile! ECHO !url1! 
Findstr /I "!url1!" "!hostsfile!" 2>&1 >NUL ||(Echo Couldn't add !url1! to !hostsfile! & goto :whereever) 
1

首先,如果你想標準錯誤重定向到NUL,那麼就2>NUL。爲了阻塞echo的錯誤,您應該將echo語句封裝在另一代括號內,並將整個代碼塊重定向到2>NUL

當您添加括號代碼塊時,要回答您的「作爲旁白」問題,幾乎可以在任何命令之前或之後放置括號。當編寫複合命令子句/條件來堅持每行一個命令並使代碼更易讀時,這非常有用。

這裏有一個例證: 「訪問被拒絕」

@echo off & setlocal 

set "hosts=%systemroot%\system32\drivers\etc\hosts" 
set "url=169.254.0.1  test" 

2>NUL (
    setlocal enabledelayedexpansion 
    >>"%hosts%" (echo !url!) && (
     echo Successfully added. 
     endlocal 
    ) || (
     echo Addition failed. Try running this as administrator. 
     exit /b 1 
    ) 
) 

exit /b 

這成功地抑制任何消息,根據需要僅回顯您指定的成功或失敗消息。

順便說一句,我做了(echo !url!),以避免迴應尾隨空間,只是因爲我認爲它比echo !url!&&更漂亮/更易於閱讀。