Ich verwende die folgenden Befehle:
%Vor%und die Ausgabe:
= & amp;: = & amp;: \
= & gt;: = & gt;: \
= A: = A: \
= B: = B: \
= C: = C: \
....
Da die Variablen =Drive:
den zuletzt aufgerufenen Pfad des entsprechenden Laufwerks speichern, sieht es so aus, als ob die Erweiterung %~fI
irgendwie auf nicht existierendes Laufwerk zugegriffen hat (was nicht möglich ist). (Alle Parametererweiterungen erzeugen solche Variablen)
Wenn ein Modifizierer im ersetzbaren Parameter for
verwendet wird, um ein Pfadelement anzufordern, verwendet der Befehl for
(nun, eine Funktion, die den Inhalt der gelesenen Variablen abruft) das GetFullPathName
Funktion, um die Eingabe-Zeichenfolge an etwas anzupassen, das bearbeitet werden kann . Diese API-Funktion (na ja, einige der von dieser API aufgerufenen OS-Basisfunktionen) erzeugt das angegebene Verhalten, wenn ein relativer Pfad angefordert wird. Sie können diesen c-Code testen (tut mir leid, nur einen schnellen Code-Test), die ausführbare Datei mit dem ex aufrufen. ;:
als erstes Argument.
um etwas wie
zu erhalten %Vor%EDITED 2016/12/23
Dies ist für Windows 10, aber da sich Windows 7 genauso verhält, sollte es denselben oder ähnlichen Code teilen.
Die Ausgabe von Umgebungszeichenfolgen an die Konsole wird von DisplayEnvVariable
function gehandhabt. In älteren Windows-Versionen (checked und XP hat es so gemacht) ruft diese Funktion GetEnvironmentStrings
auf, um die Werte abzurufen, aber jetzt (markiert und in Vista wurde geändert) wird ein Zeiger auf einen Speicherbereich verwendet. Irgendwie (in diesem Moment kann ich diesem Problem nicht mehr Zeit geben), zeigt es auf eine nicht aktualisierte Kopie der Umgebung (in diesem Fall wurde die aktualisierte nicht von cmd
-Befehl generiert, sondern von einer Basis Rtl
-Funktion wird beim Auflösen des aktuellen Laufwerkspfads aufgerufen und erzeugt das beobachtete Verhalten.
Es ist nicht notwendig, den Befehl pushd
oder cd
auszuführen. Jede Änderung an der Umgebung oder jede Prozesserstellung führt zu einer Aktualisierung des Zeigers.
Sie können die more
-Zeile durch eine einfache set "thisIsNotSet="
ersetzen, um das gleiche Ergebnis zu erhalten
Ich denke, es gibt zwei Dinge, die dazu beitragen:
Ein Laufwerksbuchstabe kann eigentlich jedes andere Zeichen als Leerzeichen sein, /
und \
. Sehen Sie sich den Befehl subst
an, der beispielsweise auch &
akzeptiert (obwohl er nicht in subst
aufgeführt ist):
for
greift nur dann auf das Dateisystem zu, wenn es wirklich erforderlich ist. Dies ist der Fall, wenn:
?
, *
) werden in der Menge verwendet (auf die das Dateisystem per Befehl for
sofort zugreifen muss); Die Erweiterung for
referenz ( %I
) benötigt Informationen aus dem Dateisystem:
~s
, ~a
, ~t
, ~z
und ~$ENV:
sind natürlich Informationen aus dem Dateisystem erforderlich; ~n
, ~x
und ~p
, und auch die entsprechenden Teile von ~f
, was nichts anderes als ~dpnx
ist, wird auf das Dateisystem zugegriffen, um den Fall beizubehalten (wenn der Pfad dies nicht tut) existieren, der ursprüngliche Fall wird beibehalten); ~n
, ~x
, ~p
und ~d
sowie ~f
muss auf das Dateisystem zugegriffen werden, falls ein relativer Pfad angegeben wird, mit oder ohne Angabe eines dedizierten Laufwerks (zum Beispiel, abc\def
, D:data
, P:
), weil der aktuelle Arbeitsverzeichnispfad (des gegebenen Laufwerks im Fall) bestimmt werden muss;
Der Modifizierer ~d
und auch der entsprechende Teil von ~f
wird durch reine String-Manipulation behandelt, solange das Dateisystem nicht gemäß den oben genannten Bedingungen aufgerufen wird.
Versuchen Sie einfach Ihren ursprünglichen Code, aber mit absoluten Pfaden, wie for %I in (a:\ b:\ c:\ ">:\" "&:\") do @rem %~fI
, usw., und Sie werden feststellen, dass es keine entsprechenden =Drive:
Variablen gibt.
Laufwerksbuchstaben können buchstäblich fast alle Zeichen sein (siehe subst
).
Sobald for
auf das Dateisystem zugreift, um nach Laufwerken und Pfaden zu suchen, werden die Laufwerke, auf die zugegriffen wird, in den Variablen =Drive:
aufgezeichnet.
Der Windows-Befehlsinterpreter versucht, den tatsächlichen Namen einer Datei oder eines Verzeichnisses auf Speichermedien mit einer Erweiterung wie %~fI
zu erhalten, indem er ein QueryDirectory
verarbeitet, wie es bei der Verwendung von Sysinternals Process Monitor angezeigt wird. Aber die Loop-Variable I
enthält nur einen String-Wert wie in set definiert.
Aus Sicht des Programmierers, was sollte der Befehlsinterpreter zum Beispiel für den folgenden Code tun?
%Vor% Es gibt höchstwahrscheinlich keine Datei mit dem Namen #abcdefghi.tmp
im Verzeichnis für temporäre Dateien für Systemprozesse. Aber die Ausgabe ist trotzdem
Der Windows-Befehlsinterpreter muss eine Zeichenfolge erstellen, da der Stapelcode eine Zeichenfolge erwartet. Es kann %%~fI
nicht durch nichts oder einen Fehlermeldungstext ersetzen, da dies bei der weiteren Verarbeitung der Befehlszeilen in der Batch-Datei zu einem undefinierten Verhalten führen würde.
Das vollständige Beenden der Stapelverarbeitung ist auch keine Option für den Windows-Befehlsinterpreter, da die FOR -Schleife verwendet werden kann, um das Vorhandensein von Dateien zu überprüfen.
Der Windows-Befehlsinterpreter versucht also, aus dem aktuellen Verzeichnis und der aktuellen Variablen-Zeichenkette einen gültigen Dateinamen mit Pfad oder einfach Dateipfad oder einfach Dateinamen zu erstellen, unabhängig vom Vorhandensein der Datei / des Verzeichnisses oder Gültigkeit der erstellten Zeichenfolge.
Der Befehlszeilenbenutzer bzw. Schreiber des Stapelcodes muss beim Erweitern der Schleifenvariablenreferenz nach Gültigkeit oder Existenz und nicht nach dem Windows-Befehlsinterpreter suchen.
Tags und Links windows cmd batch-file