2017-03-17 190 views
1

我正在尋找批處理文件在執行後將其自身移動到已知位置的方法。自我移動 - 似乎是最恰當的名字,但我確信有一個技術術語。我想在所有其他代碼都運行後移動批處理文件自動移動批處理文件

move "C:\temp\move_me.bat" "D:\temp\move_me.bat" 

其中move_me.bat是放在c:\ temp中的同名批處理文件,將其移動到d:\ temp。

我得到的錯誤

The batch file cannot be found.

即使批處理文件移動位置。所以我有點困惑。我需要抑制錯誤還是最好複製批處理文件並刪除源文件?或者有更好的方法來做到這一點?

回答

3

Windows命令提示符cmd不會在內存中緩存不批處理文件,它通過線從文件中讀取行他們。因此,只要move命令完成,您將收到錯誤,因爲無法再找到該文件。

你可以這樣調用批處理文件來取消錯誤:

"C:\temp\move_me.bat" 2> nul 

但這supresses所有其他錯誤消息也無意的。

無論如何,或許下面的方法對你的作品 - 這是腳本C:\temp\move_me.bat

if /I "%~dp0"=="D:\temp\" exit /B 
rem // (some other code here...) 
copy "%~f0" "D:\temp\%~nx0" 
"D:\temp\%~nx0" & del "%~f0" 

首先,在對D:\temp\檢查當前運行批處理文件的位置;如果相等,批處理文件立即終止。

最後,原來的批處理文件(由%~f0 訪問)被複制(不是移動)到新位置D:\temp(文件名,%~nx0,保持不變)。

下一行從新位置運行批處理文件,但不使用call,這需要返回到調用批處理腳本,但這不是我們想要的。當前一個命令完成時,& operator允許執行下一個命令。儘管未使用call,但由於整行已被cmd讀取和解析,所以仍然執行下一個命令。但執行控制現在位於批處理文件的新實例中,因此錯誤消息The batch file cannot be found.不再出現。

上述if查詢立即退出批處理文件副本的執行,所以其他代碼不會運行兩次。

如果你不想跳過複製的批處理文件的執行,刪除if命令行和修改copy命令行來得到這樣的:

rem // (some other code here...) 
copy "%~f0" "D:\temp\%~nx0" > nul || exit /B 
"D:\temp\%~nx0" & del "%~f0" 

> nul portion抑制顯示信息(包括摘要1 file(s) copied.)。只有在複製失敗的情況下,|| operator才執行下一個命令。所以當原始批處理文件執行時,複製按預期完成。當複製的批處理文件運行時,copy會嘗試將批處理文件複製到其自身,從而導致消息The file cannot be copied onto itself.(被> nul抑制),並且出現一個錯誤,該錯誤會觸發exit /B命令(由於||)離開該批處理文件,所以最後一行不會被執行。


您也可以使用move實現相同的行爲;因此,相關的代碼如下所示:

if /I "%~dp0"=="D:\temp\" exit /B 
rem // (some other code here...) 
move "%~f0" "D:\temp\%~nx0" & "D:\temp\%~nx0" 

或者,如果你想要的其他代碼不會被跳過了移動腳本:

rem // (some other code here...) 
if /I not "%~dp0"=="D:\temp\" move "%~f0" "D:\temp\%~nx0" & "D:\temp\%~nx0" 

if查詢條件是:move,而相比之下, copy,如果源和目標相等,則不返回錯誤。


下面是一個批處理文件的全面解決方案,該文件自動移動並對移動的文件進行控制。看看所有的解釋性說明,找出哪些代碼是由什麼批處理文件實例上運行:

@echo off 

rem // Define constants here: 
set "_TARGET=D:%~pnx0" & rem /* (this defines the movement destination; 
         rem  in your situation, the original batch file is 
         rem  `C:\temp\move_me.bat`, so the target file is 
         rem  `D:\temp\move_me.bat` (only drive changes)) */ 

rem // (code that runs for both batch file instances...) 
echo Batch file: "%~f0" 
echo [executed by both files before the movement check] 

rem // Check whether current batch file is the moved one: 
if /I "%~f0"=="%_TARGET%" (

    rem // (code that runs for the moved batch file instance only...) 
    echo Batch file: "%~f0" 
    echo [executed only by the moved file] 

) else (

    rem // (code than runs for the original batch file instance only...) 
    echo Batch file: "%~f0" 
    echo [executed only by the original file] 

    rem // Actually move the batch file here, then give control to the moved one: 
    > nul move "%~f0" "%_TARGET%" 
    "%_TARGET%" 

    rem /* (code that runs for the original batch file instance only; 
    rem  this is run after the moved batch file has finished; 
    rem  you must not use `goto` herein as the target label cannot be found, 
    rem  because the original file does no longer exist at this point!) */ 
    echo Batch file: "%~f0" 
    echo [executed only by the original file, but after the moved one has finished] 

) 

rem // (code that runs for the moved batch file instance only...) 
echo Batch file: "%~f0" 
echo [executed only by the moved file after the movement check] 

exit /B 

1)注意parenthesised (/)並繼續行^的代碼塊被認爲是單個命令行:

(
    echo This entire parenthesised block is 
    echo considered as a single command line. 
) 
echo This continued line &^
echo as well.

2)注意,這樣的參數的引用被立即儘快解析爲一個命令線O r塊被讀取和解析,因此在它被實際執行之前。

0

批處理文件是逐行執行的,而不是一次讀入內存。在命令move之後是否還有其他命令?

但是,批處理文件還具有調用另一個批處理文件將覆蓋批處理文件的功能。

所以,你可能能夠與閃避:

if "%1" == "continuation" goto :continuation 

REM interesting things go here 

move "C:\Temp\move_me.bat" "D:\Temp\move_me.bat" 
"D:\Temp\move_me.bat" continuation 

:continuation 
REM more interesting things go here 

或者副本您的批處理文件複製到目標,並有延續刪除原始副本。

或者讓你的批處理文件自己複製到目的地(並刪除它自己),作爲第一個的事情。這可能更容易理解。

+0

'move'後面的行不再被識別,我想。也許你可以在':continuation'部分把'move'改成'copy'並用'del'刪除原來的批處理文件...... – aschipfl

+0

...或者保留'move',但是簡單地用'&'連接下一行' ,那麼應該認識到... – aschipfl