Warum funktioniert "-P" nicht nach einer Pipe?

8
%Vor%

Was ist passiert? Laut aller Dokumentation für SET , die ich gesehen habe, hätte% V1% von oben den Wert "abcd" zugewiesen bekommen, nein?

Ich bin auf Windows XP Pro, SP3, wenn es darauf ankommt.

    
DVK 10.08.2010, 07:42
quelle

3 Antworten

11

Die Pipe scheint eine neue CMD-Instanz zu erstellen, um den nächsten Befehl auszuführen, der die Pipe-Daten empfängt. Wenn die Pipeline abgeschlossen ist, wird diese CMD-Instanz beendet und die Variable ist verloren.

    
TonyM 29.12.2010, 18:08
quelle
3

Ich weiß nicht, was doco Sie für den Befehl set gesehen haben, aber die Ausgabe von set /? besagt eindeutig:

  

Mit der Option / P können Sie den Wert einer Variablen auf eine Eingabezeile festlegen, die vom Benutzer eingegeben wurde.

(meine Kursivschrift). Ich denke, dass set /p seine Eingabe von der Konsole erhält, unabhängig davon, was Sie über die Standardeingabe eingeben möchten. Warum es nicht wartet, bin ich mir nicht sicher. echo xxx | set /p xx= kann die Variable auch nicht setzen.

Wenn Sie jedoch eine Variable aus einer einzelnen Zeilendatei setzen möchten, können Sie einfach eine der folgenden verwenden:

%Vor%

Das zweite ist das einfachste, aber es hilft nicht viel, wenn Sie die Ausgabe eines beliebigen Befehls abrufen möchten, aber Sie müssen es möglicherweise zuerst in eine Datei leiten.

Der erste erlaubt Ihnen, beliebige Befehle ohne temporäre Dateien auszuführen:

%Vor%

Auf dieser Seite gibt es ein interessantes Snippet, das vorschlägt, dass es mit Kontexten zu tun hat:

  

Ok, ich habe selbst herausgefunden warum. Das liegt daran, dass | einen neuen Kontext erstellt, sodass die Variable den Rest des aktuellen Kontextes nicht erkennt. Beweis:
> set bar=
> echo aaa | (set /p bar= && set bar)
bar=aaa
> set bar
Environment variable bar not defined

obwohl ich es ablehne, die Richtigkeit dieser Schlussfolgerung zu kommentieren. Ich weiß nicht, welche Kontexte in diesem Sinne sind, ich mache nur auf Vollständigkeit aufmerksam.

    
paxdiablo 10.08.2010 07:51
quelle
1

Dies ist keine direkte Antwort auf die ursprüngliche Frage, die Why doesn't [..] work? gefragt hat, aber diese Antwort kann nützlich sein für Leute, die versuchen, das logische Ergebnis von etwas wie dem zu erreichen:

%Vor%

Die normale Problemumgehung, zum Beispiel für den obigen Code, wäre:

%Vor%

was die Arbeit perfekt macht, außer dass es eine neue Datei erstellt, die danach behandelt werden muss (zusätzlich zu der Tatsache, dass wir zusätzliche Schritte unternehmen müssen, um sicherzustellen, dass diese neue Datei eine bestehende Datei nicht überschreibt nicht erstellt oder nie beabsichtigt, zu ersetzen).

Obwohl es wahr ist, gibt es keine Möglichkeit , einen Dateistrom zu verwenden, um die Lücke zwischen beiden Seiten des Pipe | -Operators zu überbrücken, sofern es sich um Umgebungsvariablen handelt, die sich unter Windows NT befinden Umgebung, und zur Verfügung gestellt der Datenträger, auf dem das Skript liegt, verwendet das NTFS-Dateisystem, kann man etwas viel eleganter als temporäre Dateien verwenden: alternative Datenströme

Sehen wir uns ein Beispiel an, das zeigt, wie man sie benutzen könnte:

%Vor%

Hier steht %~nx0 für den Dateinamen (Basisname + Erweiterung) unserer Batch-Datei, der in Anführungszeichen eingeschlossen wird, falls er Leerzeichen enthält.

  

Hinweis:   Wobei man stattdessen %0 direkt (ohne Anführungszeichen) verwenden könnte   Das aktuelle Skript .\%~nx0 ist besser zu verwalten, wenn Sie es jemals brauchen   Sehen Sie sich den erweiterten Wert des Befehls an, während Sie Ihr Skript debuggen,   vor allem, wenn der vollständige Pfad Ihres Skripts ziemlich lang ist.

Daher verweist ".\%~nx0":temp auf einen alternativen Datenstrom (ADS) unseres eigenen Skripts namens temp , zum Beispiel myscript.cmd:temp , das wir erstellen (oder überschreiben) mit der Ausgabe des Befehls echo . Da ADS sich genauso verhält wie der Standard-Stream einer Datei, sehen die Befehle echo und set keinen Unterschied.

Ein vollständiges Skript, das die Methode verwendet, könnte folgendermaßen aussehen:

%Vor%

Hier, am Ende des Skripts, wird die Zeile type nul> %__self%:%__adsname , die zu etwas wie type nul> ".\myscript.cmd":test.dat erweitert werden könnte, verwendet, um den Inhalt des gerade verwendeten alternativen Datenstroms zu löschen. Obwohl dies die Größe des alternativen Datenstroms auf Null setzt, löscht er nicht (siehe unten).

Einige abschließende Anmerkungen:

  1. Die meisten Befehle können alternative Datenströme nicht verstehen oder mit ihnen arbeiten, wenn sie als Quelldateien bereitgestellt werden. Dies bedeutet, dass die folgenden nicht verwendet werden können:

    • type , z.B. %Code%
    • type myscript.cmd:data > myscript_data.txt , z.B. %Code%
    • copy , z.B. %Code%
    • copy myscript.cmd:data myscript_data.txt / move , z.B. %Code%
    • move myscript.cmd:data myscript_data.txt / del , z.B. %Code%
    • und so weiter

    Tatsächlich ist es nur die Dateiumleitung, die alternative Datenströme unterstützt mit einer Ausnahme (was ich mir vorstellen kann): den Befehl erase .

  2. Obwohl wir den Inhalt eines alternativen Datenstroms recht einfach löschen / löschen können, ist das Löschen ziemlich kompliziert, da das Kopieren einer Datei oder das Umbenennen keine Streams enthält (naja del myscript.cmd:data eins) und das Bearbeiten / Ändern des Inhalts einer Datei wirkt sich nur auf den Standarddatenstrom aus. Dennoch haben wir je nach dem, was wir erreichen wollen, einige Optionen:
    • Wenn wir nur einen einzigen alternativen Datenstrom haben oder nichts dagegen haben, alle auf einmal zu löschen, und der Inhalt der Datei ist nur Text, dann wir Sie können eine neue Datei erstellen, indem Sie only den Standarddatenstrom der ursprünglichen Datei mit dem folgenden Befehl ren beibehalten, nach dem die ursprüngliche Datei gelöscht werden kann.
    • Wenn wir Administratorrechte für das Volume und unter Windows Vista oder einer höheren Version des Betriebssystems haben, können wir MKLLINK , um eine symbolische Verknüpfung zu einem alternativen Datenstrom zu erstellen, der uns dann einen Standarddateinamen liefert, der mit den üblichen Dateiverwaltungsbefehlen verwendet werden kann.
    • Alternativ können Sie auch eines der vielen verfügbaren Tools verwenden, um alternative Datenströme wie Streams zu bearbeiten , LADS oder AlternateStreamView .
  3. Ein nützlicher Befehl zum Auflisten regulärer Dateien einschließlich alternativer Datenströme von der Befehlszeile ist rename . Sie können dann jedes Programm verwenden, um auf den Namen- (alternativen) Datenstrom einer Datei zuzugreifen, z. %Code%

Ich hoffe, das hilft!

    
johnwait 17.12.2015 07:21
quelle

Tags und Links