Wenn Sie cd..
ohne Leerzeichen zwischen cd
und eingeben, wechselt ..
die Windows-Eingabeaufforderung problemlos zum übergeordneten Ordner. Gibt es eine Erklärung für dieses Verhalten? Der Befehl folgt nicht dem Standardformat voncommand<space>arguments
Warum führt dies nicht zu konsistenten Ergebnissen?
windows
command-line
command-line-arguments
Jonas Köritz
quelle
quelle
dir/a
die ähnliche VMS-Syntax.cd c:\program files
ohne Anführungszeichencd..
arbeitet? Weil Microsoft sich die Mühe gemacht hat, es explizit zum Laufen zu bringen.cd
ist ein Befehl, der in den Windows-Befehlsinterpreter integriert ist, und Microsoft kann den Interpreter dazu bringen, dass er tut, was er will. (Als weiteres Beispiel müssencd
auch keine Verzeichnisse mit Leerzeichen im Namen inAntworten:
Wie einige der anderen Antworten / Kommentare bemerken, ist die Vorstellung, dass nach dem Befehl ein Leerzeichen stehen muss, nicht korrekt. Ein bekanntes Beispiel ist, dass Sie nach einem Befehl einen Schrägstrich eingeben können, ohne zuerst ein Leerzeichen zu benötigen.
Es gibt jedoch ein anderes Verhalten, das etwas weniger verstanden wird und das "
cd..
" zulässt, nach dem Sie fragen. Dieses Verhalten ermöglicht es auch, "cd\
" zu funktionieren.Das von Ihnen beschriebene Verhalten gilt für alle befehlsinternen Befehle des Befehlszeileninterpreters. Wenn Sie bestimmte Symbole wie Punkte, Schrägstriche oder umgekehrte Schrägstriche verwenden, werden die vorherigen Zeichen überprüft, um festzustellen, ob es sich um einen Befehl handelt, der in der Shell des Befehlszeileninterpreters (CMD.EXE oder dessen Vorgänger COMMAND.COM) enthalten ist ).
Dies kann erfolgen, bevor geprüft wird, ob das Wort auf eine Datei oder ein Unterverzeichnis verweist. Das gilt für den
cd
Befehl. Tragischerweise stellte ich bei der Erstellung eines Beispiels fest, dass dies bei demcopy
Befehl nicht der Fall ist , sodass die Ergebnisse inkonsistent sind: Sie müssen nicht bei allen internen Befehlen gleich sein. Ich habe meine Suche nicht fortgesetzt, um auch (viele) andere Befehlszeilen zu vergleichen,del
unddir
deshalb empfehle ich, äußerst vorsichtig zu sein, wenn Sie versuchen, sich darauf zu verlassen, was ohne Leerzeichen passiert.Nun wurde auch die Frage nach dem Echo- Befehl gestellt: Dies ist eine ungewöhnliche Ausnahme, da ich denke, dass
echo.
sie DOS-Experten ziemlich gut bekannt ist. Dies wurde wahrscheinlich dokumentiert. Zumindest in Win7's CMD ist das Verhalten, dass, wenn der Befehl mit "echo.
" beginnt , der erste Punkt ignoriert wird. "echo..hi
" Wird also zur Ausgabe von ".hi
". Der Grund dafür ist, dass mit "echo.
" eine Leerzeile gedruckt werden kann. Im Gegensatz dazu können Sie dies unter Unix einfach tun, indem Sie denecho
Befehl " " selbst ausführen. Wenn Sie jedoch unter DOS denecho
Befehl " " selbst ausführen, wird die aktuelle Einstellung " echo " ausgegeben . Ebenso behandelt DOS "Echo *Off*
" und "Echo *On*
msgstr "Off
" "als spezielle Werte, die die aktuelle Echoeinstellung ändern. Wenn Sie das Wort" " tatsächlich drucken möchten,Echo.Off
erledigt " "dies (zumindest mit den neuesten Versionen des CMD - Befehlszeileninterpreters von Microsoft ).Zumindest der
echo
Befehl hat also eine halbwegs vernünftige Erklärung. Bei den restlichen Befehlen war ich der Meinung, dass interne Befehle Vorrang haben. Als ich jedoch versuchte, einige Tests durchzuführen, stellte ich fest, dass dies tatsächlich ziemlich inkonsistent ist. Ich zeige dies anhand einiger Beispiele, die ich hier dokumentiert habe.Hier sind einige Beispiele. Ich habe eine Eingabeaufforderung mit erhöhten Rechten verwendet, damit sich die Benutzerkontensteuerung nicht darüber beschwert, dass ich in das Stammverzeichnis schreibe. Dies wurde mit CMD.EXE von Microsoft Windows 7 durchgeführt. Ich vermute, dass sich das Verhalten bei anderen Versionen wie COMMAND.COM von älteren MS-DOS-Versionen oder von Software anderer Hersteller (COMMAND.COM von DR-DOS) unterscheidet.
(Diese Antwort ist schon ziemlich lang, daher füge ich keine Befehle zum Bereinigen der Unordnung ein, die ich in meinem Dateisystem angerichtet habe. Es gibt ein kleines Stück Bereinigung, aber nicht viel.)
Das folgende Beispiel zeigt, dass der interne Befehl Vorrang hat. (Ich zeige auch die wenig bekannte Fähigkeit, einen Doppelpunkt effektiv als Kommentar zu verwenden, was auch in Batch-Dateien gut funktioniert. Technisch gesehen wird er in Batch-Dateien als Etikett verarbeitet, das von GOTO nicht erreicht werden kann, und endet schneller sein als der REM-Befehl.)
In diesem Beispiel wird demonstriert , dass eine Kopie mit vollständigem Pfad nicht dieselbe Priorität (bevorzugt den internen Befehl) wie cd verwendet, wenn keine Erweiterung verwendet wird:
Meine ersten Ergebnisse zeigten, dass diese Ergebnisse zeigen, dass die Befehlszeilen-Shell Priorität hat:
Dies zeigt deutlich, dass das Verhalten zwischen dem Befehl copy (mit einem vollständigen Dateinamen einschließlich einer Erweiterung) und dem Befehl cd (ohne eine Erweiterung als Teil des Verzeichnisnamens) nicht konsistent ist . Bei Verwendung eines umgekehrten Schrägstrichs überprüft der Befehl copy (mit der vollständigen Dateinamenerweiterung) zuerst das Dateisystem, der Befehl cd jedoch nicht (wenn das Verzeichnis keine Erweiterung enthält).
(Update: Zuerst dachte ich, dass die Inkonsistenz auf unterschiedlichem Verhalten zwischen den Programmen basiert. Später stellte ich fest, dass die Inkonsistenz vorhanden war, aber mehr von den bereitgestellten Parametern verursacht wurde.)
Tatsächlich sind auch diese Stichpunkte nicht ganz korrekt, obwohl ich anscheinend alles demonstriert habe, was ich gerade gesagt habe. Das Problem ist, dass die Liste der Aufzählungspunkte nicht genau genug ist, um vollständig korrekt zu sein. (Ich habe die Dinge ungenau gelassen, damit diese Aufzählungszeichen relativ leicht verglichen und relativ leicht überprüft werden können.)
Genauer gesagt sollte der erste Aufzählungspunkt jedoch darauf hinweisen, dass die Befehlszeilen-Shell Priorität hat:
Das Folgende wird zeigen, warum ich diese Unterscheidung mache:
(Beachten Sie, dass die letzte Kopie Befehl für die Datei sah genannt \ needext , da die interne Kopie Befehl verwendet wurde. Die Datei \ needext.bat nur leicht erstellt wurde zu helfen , zeigen , dass es nie von den Befehlszeilen verwendet wurde, die das Wort enthalten Kopie .)
Zu diesem Zeitpunkt habe ich eine Inkonsistenz (mit dem Verhalten des Kopierbefehls ) festgestellt, wenn ein Backslash verwendet wird ...
Als nächstes werde ich zeigen, dass es eine gewisse Konsistenz zwischen diesen Befehlen gibt. (Es gibt also Konsistenz ... ähm ... manchmal. Wir haben möglicherweise nur inkonsistente Konsistenz.) Als Nächstes zeige ich, dass sich der Befehl cd eher wie der Befehl copy verhält, wenn ein Punkt verwendet wird. Der Befehl copy verwendet den internen Befehl und auch den Befehl cd .
Während der ersten Testsitzung, die sich hauptsächlich auf die Befehle cd und copy konzentrierte (mit etwas zusätzlicher Verwendung von md und etwas del ), war das einzige Mal, dass das Dateisystem wirklich Priorität hatte, der Befehl copy und dann der Befehl Das Dateisystem hatte nur dann Priorität, wenn der vollständige Pfad verwendet wurde.
Nach der anschließenden Überprüfung stellte ich fest, dass der Befehl cd dem Dateisystem bei Verwendung einer Erweiterung ebenfalls Priorität einräumte. Zumindest bedeutet dies, dass die internen Befehle etwas konsistenter behandelt werden. Dies bedeutet jedoch auch, dass wir ein unterschiedliches Verhalten erhalten, das auf den Namen der Dateisystemobjekte (der Dateien oder Verzeichnisse) basiert. Das scheint, als würde das Verhalten eine wirklich, wirklich undurchsichtige interne Logik verwenden. Daher würde ich es wahrscheinlich als unsicher erachten, mich auf dieses Verhalten zu verlassen, um unter verschiedenen Betriebssystemen zu arbeiten.
quelle
ipconfig
zum Beispiel funktioniert auch.IPCONFIG/ALL
. Darüber habe ich jedoch nicht gesprochen. " Das Verhalten, das Sie beschreiben " (in Ihrer Frage) war das Verhalten, einen Punkt direkt nach dem Befehlsnamen zu setzen. Wenn ich tippe,IPConfig.
erhalte ich eine Fehlermeldung, dass ein Befehl nicht gefunden wurde. In ähnlicher Weise (obwohl dies nicht mit dem von Ihnen beschriebenen Verhalten zusammenhängt)IPCONFIG\ALL
kann ich bei der Eingabe eine benutzerdefinierte.\IPCONFIG\ALL.BAT
Datei ausführen , die ich erstellt habe. Also/
's werden nicht wie ".
oder" behandeltcopy.exe
odercopy.com
in cmd auszuführen . Es funktioniert nicht - es ist keine ausführbare Datei.ipconfig
Ihrer Schlussfolgerung bin ich nicht einverstanden. Bei dieser Frage geht es darum, was am Anfang einer Befehlszeile eingegeben wird. Windows / DOS identifiziert ausführbare Dateien anhand der Dateinamenerweiterung. Sie können daher kein Programm mit dem Namen "ipconfig" ohne eine Erweiterung ausführen (unter Windows im Gegensatz zu Unix, das dies zulässt). Bezüglich des nächsten Kommentars weiß ich nicht, wer "Calchas" ist. (Wenn Sie ein at-Zeichen angeben, werden im Folgenden normalerweise die ersten Zeichen eines Benutzers aufgeführt, die an einer anderen Stelle auf der Seite angezeigt werden.) Ich bin damit einverstanden, dass beim Ausführen von "copy.exe
" der internecopy
Befehl verwendet wird (und übergeben wird.exe
). (Sie können rennen.\copy.exe
)Sie gehen davon aus, dass ein Befehlsname und seine Argumente durch ein Leerzeichen getrennt sein müssen. Dies ist jedoch nicht der Fall. Solange der Aufruf eindeutig interpretiert werden kann, ist der Aufruf gültig.
In diesem Fall beginnt das erste Argument mit
.
und.
nicht Teil des Befehlsnamen sein kann, socd
und..
werden einfach als zwei getrennte Token analysiert.Normalerweise beginnt Ihr erstes Argument mit einem Buchstaben (z. B. dem Anfang eines Pfads), sodass es in Ihren Befehlsnamen "übergeht" und einen Fehler verursacht. Dies ist jedoch kein Syntaxproblem. Es ist eine semantische.
Sie können den gleichen Effekt bei der Arbeit mit anderen Befehlen sehen, einschließlich
echo
:In diesem Fall erhalten wir nur zwei Punkte, da der
echo
Befehl selbst eine spezielle Regel hat , so dass Folgendes gilt:oder im weiteren Sinne:
gibt nur eine leere Zeile aus. Es ist eine Annehmlichkeit. Anscheinend wurde es implementiert, indem ein führender Punkt in dem Argument ignoriert wurde.
Hey, das ist DOS / Batch. Du willst geistige Gesundheit? : D
quelle
cd..
cd..
:)alias cd..='cd ..'
.
und..
die erscheinen als Verzeichnisse in jedem anderen Verzeichnis und waren meines Wissens nie dazu gedacht, mehr als das zu fangen. Ich betrachte Hidden-Ness, das als Dateiattribut modelliert wurde, als saubereres Design, als implizit aus dem Dateinamen zu folgen..
Dateinamen zuließ , was bedeutete, dass es nicht Teil eines Befehlsnamens sein konnte. Daher muss dies Teil des Arguments gewesen sein . Selbst wenn DOS den Befehl wie in Unix-Shells in Argumente unterteilt hätte, würde es dennoch ein.
nach dem Befehl stehendes Argument in das erste Argument einfügen, da es keinen Sinn macht, ein ungültiges Zeichen in den Befehlsnamen einzufügen.Der
cd..
Befehl ist korrekt und wurde wie im ursprünglichen Befehlsinterpreter definiert,command.com
der später benannt wurdecmd.exe
.Der Befehlsinterpreter weiß, wie er zu verarbeiten ist
cd..
, weil er.
genau wie ein Sonderzeichen ist\
.quelle
echo.
funktioniert genauso gut, wodurch eine leere Zeile gedruckt wird..
wird nicht fallen gelassen sondern nur ein Leerzeichen hinzugefügt.md.test
undmd .test
beide erstellen das Verzeichnis.test
. Tippen Siecd.test
undcd .test
wechselt in das Verzeichnis.test
.Es ist ein Abwärtskompatibilitäts-Hack.
Der Befehlszeileninterpreter ist abwärtskompatibel mit Befehlen des ursprünglichen MSDOS-Befehlsinterpreters, der abwärtskompatibel mit dem CP / M-Befehlsinterpreter konzipiert wurde. Weder CP / M noch MSDOS erlaubten ein
.
in einem Dateinamen (es wurde als Trennzeichen zwischen zwei Teilen des Dateinamens, dem Basisnamen und der Erweiterung interpretiert). Dies bedeutete, dass (zumindest für frühe DOS-Versionen) der Befehlsinterpreter dies identifizieren konnte, wenn ein '.' Erreicht wurde. (oder in der Tat jedes andere Zeichen, das in einem Dateinamen unzulässig war), übergab es das Ende des Befehlsnamens und wurde in die Befehlsargumente aufgenommen. Dies wurde ziemlich häufig sowohl in DOS als auch in CP / M verwendet - zum Beispieldir/w
war es ein sehr häufiger Befehl, der derdir /w
Bedeutung zum Auflisten von Dateien in einem horizontalen Format entspricht.Heutzutage, '.' kann in Dateinamen erscheinen. Dies führt zu einigen Komplikationen beim Parsen von Befehlen. Die Shell identifiziert jedoch weiterhin einen
.
Dateinamen, der nicht Teil eines exakten Dateinamens ist, als den Anfang von Argumenten. Dies ist vor allem deshalb erforderlich, weil sich Millionen von Benutzern an das Tippen gewöhnt habencd..
oder über eine große Anzahl von Batch-Dateien verfügen, die dieseecho.
oder eine beliebige Anzahl ähnlicher Befehle enthalten.quelle