die Windows-Eingabeaufforderung cmd
nicht Cache-Batch-Dateien im Speicher, liest sie aus der Datei Zeile für Zeile . Daher erhalten Sie einen Fehler, sobald der Befehl move
beendet ist, weil die Datei nicht mehr gefunden werden kann.
Sie können die Batch-Datei wie folgt aufrufen, den Fehler zu unterdrücken:
Nachrichten
"C:\temp\move_me.bat" 2> nul
Aber diese unterdrückt alle anderen Fehler auch unbeabsichtigt.
Wie auch immer, vielleicht der folgende Ansatz funktioniert für Sie - das ist das Skript 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"
Zunächst wird die Lage der aktuell laufen Batch-Datei gegen D:\temp\
geprüft wird; Wenn es gleich ist, wird die Batch-Datei sofort beendet.
schließlich die ursprüngliche Batchdatei (Zugriff durch %~f0
) kopiert wird (nicht verschoben) an den neuen Standort D:\temp
(Dateinamen, %~nx0
, gleich bleibt).
Die nächste Zeile führt die Batch-Datei von der neuen Position, aber ohne call
, die benötigt wird, um an das aufrufende Batch-Skript zurückzukehren, aber das ist nicht was wir wollen.Die &
operator lässt den nächsten Befehl ausführen, wenn der vorherige beendet ist. Obwohl call
nicht verwendet wird, wird der nächste Befehl weiterhin ausgeführt, da die gesamte Zeile bereits von cmd
gelesen und analysiert wurde. Die Ausführungssteuerung befindet sich jetzt jedoch in der neuen Instanz der Stapeldatei, sodass die Fehlermeldung The batch file cannot be found.
nicht mehr angezeigt wird.
Die zuvor erwähnte if
Abfrage beendet die Ausführung der Kopie der Stapeldatei sofort, so dass der andere Code nicht zweimal ausgeführt wird.
Falls Sie nicht wollen, um die Ausführung der kopierten Batch-Datei überspringen, entfernen Sie die if
Befehlszeile und ändern Sie die copy
Befehlszeile dieses zu erhalten:
rem // (some other code here...)
copy "%~f0" "D:\temp\%~nx0" > nul || exit /B
"D:\temp\%~nx0" & del "%~f0"
Die > nul
portion Displaymeldungen unterdrückt (einschließlich der Zusammenfassung 1 file(s) copied.
). Der ||
operator führt den nächsten Befehl nur aus, wenn der Kopiervorgang fehlschlägt. Wenn die ursprüngliche Stapeldatei ausgeführt wird, wird das Kopieren wie erwartet ausgeführt. Wenn die kopierten Batch-Datei ausgeführt wird, copy
versucht die Batch-Datei auf sich selbst zu kopieren, die in der Nachricht führt The file cannot be copied onto itself.
(unterdrückt durch > nul
) und in einem Fehler, der den exit /B
Befehl (wegen ||
) feuert die Batch-Datei zu verlassen, so dass die Die letzte Zeile wird nicht ausgeführt.
Sie können das gleiche Verhalten auch mit move
erreichen; so dass der zugehörige Code sieht wie folgt aus:
if /I "%~dp0"=="D:\temp\" exit /B
rem // (some other code here...)
move "%~f0" "D:\temp\%~nx0" & "D:\temp\%~nx0"
Oder, wenn Sie die anderen Code wollen nicht für das bewegte Skript übersprungen werden:
rem // (some other code here...)
if /I not "%~dp0"=="D:\temp\" move "%~f0" "D:\temp\%~nx0" & "D:\temp\%~nx0"
Die if
Abfrage ist notwendig, da move
, im Gegensatz zu copy
, gibt keinen Fehler zurück, wenn Quelle und Ziel identisch sind.
Hier ist eine umfassende Lösung für eine Batch-Datei, die sich selbst bewegt und die Kontrolle über die bewegte nachher gibt. Werfen Sie einen Blick auf all die Erläuterungen, um herauszufinden, welcher Code durch welche Batch-Datei-Instanz ausgeführt wird:
@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) Beachten Sie, dass Codeblöcke parenthesised (
/)
und weiterhin Linien ^
gelten als eine einzige Befehlszeile: Hinweis
(
echo This entire parenthesised block is
echo considered as a single command line.
)
echo This continued line &^
echo as well.
2), dass solche Argument Referenzen werden sofort, sobald eine Befehlszeile o aufgelöst r Block wird gelesen und geparst, also bevor es tatsächlich ausgeführt wird.
Die Zeile nach 'move' wird nicht mehr erkannt, denke ich. Vielleicht könnten Sie 'move' in' copy' ändern und die ursprüngliche Batch-Datei mit 'del' im': continuation'-Abschnitt löschen ... – aschipfl
... oder 'move' behalten, aber einfach die nächste Zeile mit' & 'verketten dann sollte es erkannt werden ... – aschipfl