2014-03-27 270 views
0

我一直在用StackOverflow之類的線程研究過很多,但儘管我覺得我接近解決方案,但這個問題讓我頭疼。處理Windows批處理文件for循環中的變量

我在做什麼:當連接一個特定的外部硬盤驅動器(通過WMIC上的VolumeSerialNumber進行區分)時,驅動器號被發現,鏡像通過robocopy完成。該腳本通過雙擊執行。這是我到目前爲止有:

FOR /F "skip=1" %%i in ('wmic logicaldisk where VolumeSerialNumber^="XXXXXXXX" get deviceid 2^>nul') DO (
    SET y=%%i 
    IF [%y%]==[] GOTO hdmissing 
    SET "backuphd=%%i" 
    GOTO endfor 
) 
:endfor 

robocopy "C:\Users\Herbert\Documents" "%backuphd%\Backup\Documents" /MIR 

ECHO Backup done 
ECHO end 

:hdmissing 
ECHO Couldn't find external drive 

:end 
PAUSE 

這樣,外部HD是永遠不會檢測(%y%始終是一個空字符串)。但是,如果我在同一個控制檯會話中執行兩次腳本,一切都按預期工作。但我希望它能在第一次執行時工作。

這是我到目前爲止已經試過:

  • SET y=dummy在腳本的開始。高清總是發現,觸發備份到C:如果HD實際上並沒有連接(顯然SET y=%%i不會改變y?)
  • 變化%y%!y! - 高清總是發現,再次

回答

2

第3代中的3,576個問題,由受污染的環境複合而成。

沒有setlocal明顯,所以y仍然在第一次運行後設置在環境中 - 因此「後期運行特徵與第一次運行不同」現象。

在塊語句(a parenthesised series of statements),所述整個塊被解析並然後執行。該塊內的任何%var%將在該塊被解析時由該變量的值取代 - 在塊執行之前 - 同樣的事情適用於FOR ... DO (block)

因此,在遇到IF時,將使用%variables%的值執行IF (something) else (somethingelse)。克服這個

兩種常用方法是:1)使用setlocal enabledelayedexpansion並使用!var!代替%var%訪問的var改變的值或2),以調用一個子程序使用改變的值來執行進一步的處理。除非delayedexpansionsetlocal命令調用一個字符串!y! -

你的情況的關鍵似乎是沒有setlocal enabledelayeexpansion!y! - 因爲!y!就是這樣。

(話說回來,

IF [%%i]==[] GOTO hdmissing 

將工作一樣好,因爲會

SET "y=%%i" 
IF not defined y GOTO hdmissing 

因爲if [not] defined var上的var運行時間值運行。"quoting the set arguments"確保線路上的任何雜散尾隨空格中不包括)分配 值

+0

謝謝,我不完全意識到延遲擴展的工作原理。如果我有足夠的聲望,我會提高你的答案,但我解決了它的不同(見我的詳細答案)。在延期爆炸下逃跑是一場噩夢。 'IF [%% i] == [] GOTO hdmissing'不能正常工作,因爲[WMIC在最後返回](http://stackoverflow.com/questions/19471675/removing-carriage-return -from-wmic-output),並且這似乎不被解釋爲換行符,而是作爲自己的字符。我想'SET Y = %%我'擺脫了。 '如果沒有定義y GOTO hdmissing'在我的機器上無法使用。 – user2009388

0

正如脫線已經指出,!y!不工作,因爲我忘了讓Delayed Expansion。然而,啓用它需要你逃脫某些角色,這對我來說似乎相當惱人和乏味。可以用雙引號將命令放在FOR循環中,就像在this question這兩個編輯中所做的那樣,但是在解決它之後我發現了它。

我所做的就是:endfor後移動塊

IF [%y%]==[] GOTO hdmissing 
SET "backuphd=%%i" 

。這樣,它就不在for循環中,並且%y%也相應地擴展了。

請注意,此解決方案的工作原理僅僅是因爲我只需要一個項目,並且是因爲編程流程。

其他有用的方法可以在this question中找到。

但是,如果你想要做同樣的事情:容易(雖然不是強大的)解決方案,而WMIC可能包括

  • 硬盤驅動器上放置一個文件有一個特定的名稱,並與IF EXIST檢查它在備份之前,希望用戶不會刪除它,並且HD連接到相同的驅動器號。
  • 把批處理腳本驅動器本身和工作使用相對路徑名。(可選:把桌面上的快捷方式,並希望再次驅動始終是相同的字母下)