Dir wurde in Set weitergeleitet

Dir wurde in Set weitergeleitet

Ich versuche, ein Programm zu erstellen, das einen Dateinamen auswählt und ihn dann in eine Variable weiterleitet.

Mein Versuch:

Dir /B "C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1" | (set /p myVar= & set myVar)

Nach Gebrauch gibt es

myVar:1.14.4

der Plan war, dass es in einen Echo-Befehl übergeht, also habe ich es so gemacht

@echo off
Dir /B "C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1" | (set /p myVar= & set myVar)
echo e %myVar%
cmd /k

aber alles was passiert ist

e

Was mache ich falsch? Gibt es außerdem eine Möglichkeit, dies mit FOR zu tun?

Antwort1

Was mache ich falsch?

Ganz einfach: Sie versuchen, eine Technik zu verwenden, die nicht funktionieren kann. ;-) Aufgrund der Funktionsweise von Windows-Pipes ist es nicht möglich, die Ausgabe eines Pipe-Befehls zum Festlegen von Umgebungsvariablen in Ihrer übergeordneten Umgebung zu verwenden.

Ihr Skript wird in einem Befehlsprozess ausgeführt – nennen wir ihn das übergeordnete Skript.

Eine Windows-Pipe startet zwei untergeordnete Befehlsprozesse, jeder mit seinem eigenen separaten Umgebungsbereich. Die linke Seite der Pipe wird im ersten untergeordneten Prozess ausgeführt, die rechte im zweiten. Die Pipe sendet die Ausgabe des ersten untergeordneten Prozesses als Eingabe an den zweiten untergeordneten Prozess. Die SET /Pneue Variable myVar wird erfolgreich im untergeordneten Prozess definiert und der SET MYVARBefehl zeigt den Wert an. Super.

Dann endet die Pipe jedoch, und beide untergeordneten Prozesse werden beendet, und ihre zugehörigen Umgebungen verschwinden. Es gibt keine Möglichkeit, den myVar-Umgebungswert vom untergeordneten Pipe-Prozess zurück in Ihre übergeordnete Umgebung zu übertragen.

Es gibt viele überraschende Nebenwirkungen des Windows-Pipe-Designs, die jeden verwirren, der den Mechanismus nicht vollständig versteht. Siehehttps://stackoverflow.com/q/8192318/1012053für weitere Informationen. Ich empfehle, die Frage und alle Antworten zu lesen.

Gibt es eine Möglichkeit, dies mit FOR zu tun?

Ja, die richtige Methode, die Ausgabe eines Befehls in einer Umgebungsvariable zu erfassen, ist über FOR, insbesondere FOR /Fwie DavidPostill zeigt. Allerdings gibt es in seinem Code ein eindeutiges Problem, ein potenzielles Problem und eine Ineffizienz.

Es ist nicht notwendig, USEBACKQdie Ausgabe eines Befehls zu verwenden. Es ist einfacher, normale einfache Anführungszeichen 'anstelle des Backticks zu verwenden:for /f %%F in ('yourCommand') do ...

Der Fehler liegt in der Verwendung von echo myVar:%myVar%innerhalb des FOR-Schleifenkörpers. Dadurch wird der Wert angezeigt myVar, der vor Ausführung der Schleife vorhanden war, da beim Parsen der Zeile eine prozentuale Erweiterung erfolgt und die gesamte FOR-Schleife in einem Schritt geparst wird. Sie müssten die verzögerte Erweiterung ( setlocal enableDelayedExpansion) aktivieren und dann verwenden, echo !myVar!um den Wert anzuzeigen, der innerhalb der Schleife festgelegt wurde.

Es besteht möglicherweise ein weiteres Problem: FOR /F analysiert den Wert in durch Leerzeichen getrennte Token und erfasst nur das erste Token. Wenn Ihr Dateiname Leerzeichen enthält, erhalten Sie nicht den gesamten Namen, es sei denn, Sie verwenden die Option DELIMS, um kein Trennzeichen anzugeben.

for /f "delims=" %%F in (....) do .... 

Es besteht jedoch keine Notwendigkeit, DIR /Bund zu verwenden. Sie können einfach eine Standardschleife ohne die Option FOR /Fverwenden .FOR/F

Im Folgenden werden beispielsweise einfach alle Dateien aufgelistet:

for %%F in ("C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1\*") do echo %%~nxF

Gibt ~nxan, dass nur der Dateiname und die Erweiterung verwendet werden sollen, während Laufwerk und Ordnerpfad verworfen werden.

Normalerweise ist die Verwendung einer Umgebungsvariablen nicht erforderlich. Nutzen Sie %%Ffür Ihre Arbeit einfach die FOR-Variable in Ihrer Schleife.

Wenn Sie jedoch aus irgendeinem Grund einen Wert außerhalb der Schleife benötigen, können Sie dies sicherlich tun

for %%F in ("C:\Program Files (x86)\ServerMaster\Internals\Versions\Van1\*") do set "myVar=%%~nxF"

Dadurch wird jedoch nur die letzte iterierte Datei erfasst. Die Variable myVar wird bei jeder Iteration überschrieben. Ihr ursprüngliches Design hätte die erste aufgelistete Datei erfasst (vorausgesetzt, es hätte funktioniert). Beides scheint keine gute Idee zu sein, es sei denn, Sie wissen genau, dass der Ordner Van1 nur eine einzige Datei enthält.

Wenn Sie alle Dateien in Variablen erfassen müssen, müssen Sie ein Pseudoarray verwenden. Batch hat kein formales Array-Konzept, kann aber leicht emuliert werden. Sie können zahlreiche Beispiele finden, wenn Sie im Internet einfach nach „Batchfile-Array“ suchen.

verwandte Informationen