Windowsのコマンドラインで「cd ..」が機能するのはなぜですか?


86

cd..間にスペースを入れずに入力するcd..、Windowsコマンドプロンプトが喜んで親フォルダーに切り替わります。この動作の説明はありますか?コマンドは、次の標準形式に従っていませんcommand<space>arguments

働いているべきではない?

また、なぜこれは一貫した結果を作成しないのですか?

エコー..


24
あなたの質問の前提は壊れているようです。これが構文的に間違っているという主張の証拠を提供できますか?
オービットのライトネスレース

13
「command <space> arguments」はこれまでcmd(またはその先行バージョン)の標準形式ではなかったと思います。例dir/aまたは同様のVMS構文を検討してください。
grawity

6
cdは非常に特別です。次のように入力することができcd c:\program files、引用符なしで、それはまだ動作します
phuclv

20
ここでは、Windowsのシェルロジックの癖を説明して非常に面白い記事があり、それが引き起こす可能性がありますどのような騒乱:thedailywtf.com/articles/The-Core-Launcher
VSZ

3
なぜ機能するのcd..ですか?Microsoftが明示的に機能させるというトラブルを経験したためです。cdWindowsのコマンドインタープリターに組み込まれたコマンドであり、Microsoftはインタープリターに必要な処理を実行できます。(別の例としてcd、名前にスペースを含むディレクトリを引用
符で囲む

回答:


106

他の回答/コメントの一部に記載されているように、コマンドの後にスペースが必要だという考えは正しくありません。よく知られた例は、最初にスペースを必要とせずに、コマンドの後にスラッシュを入力できることです。

しかし、もう少し理解されていない別の動作があり、cd..あなたが尋ねている「」を許可します。この動作により、「cd\」も機能します。

説明する動作は、コマンドラインインタープリター内部のすべてのコマンドで一貫しています。ピリオド、スラッシュ、またはバックスラッシュを含む特定の記号がある場合、前の文字が「コマンドラインインタープリター」シェル(CMD.EXEまたはその先行コマンドCOMMAND.COMの内部にあるコマンドであるかどうかを確認するためにチェックされます。 )。

これは、単語がファイルまたはサブディレクトリを指している可能性があるかどうかをチェックする前に行うことができます。これはcdコマンドにも当てはまります。悲劇的なことに、サンプルを作成するとき、これはcopyコマンドでは発生しないことがわかったため、結果には一貫性がありません。すべての内部コマンドで必ずしも同じとは限りません。他のコマンドラインdelとを比較するために検索を続行しませんでしたdirので、スペースなしで何が起こるかに依存しようとする場合は、非常に注意することをお勧めします。

さて、質問はechoコマンドについても尋ねました。これは異常な例外であり、echo.DOSの専門家にはかなりよく知られていると思います。これはおそらく文書化されました。少なくともWin7のCMDの動作では、コマンドが「echo.」で始まる場合、最初のピリオドは無視されます。したがって、「echo..hi」は「.hi」の出力になります。これは、「echo.」を使用して空白行を印刷できるようにするためです。対照的に、Unixでは、「echo」コマンドを単独で実行するだけでこれを行うことができます。ただし、DOSでは、「echo」コマンドを単独で実行すると、現在の「echo」設定が出力されます。同様に、DOSは " Echo *Off*"および "Echo *On*「現在のエコー設定を変更する特別な値として。実際に単語「Off」を出力したい場合、「Echo.Off」はトリックを行います(少なくともMicrosoftのCMDコマンドラインインタープリターの最近のバージョンでは)。

そのため、少なくともechoコマンドには半合理的な説明があります。残りのコマンドについては、内部コマンドが優先されると考えていました。しかし、いくつかのテストを行おうとしたときに、実際にはかなり矛盾していることがわかりました。ここで文書化したいくつかの例を使用して、これを示します。


下記は用例です。昇格したコマンドプロンプトを使用したので、UACがルートディレクトリへの書き込みを心配することはありません。これは、Microsoft Windows 7のCMD.EXEで行われました。古いMS-DOSバージョンのCOMMAND.COMや、他社がリリースしたソフトウェア(DR-DOSのCOMMAND.COM)など、他のバージョンでは動作が異なる可能性があります。

(この回答はすでにかなり長いので、ファイルシステムで行った混乱をすべてクリーンアップするコマンドは含めていません。クリーンアップは少しありますが、それほど多くはありません。)

内部コマンドが優先順位を作成することを証明する例はここにあります。(二重コロンを使用してコメントとして効果的に機能するあまり知られていない機能も示します。これはバッチファイルでもうまく機能します。技術的には、バッチファイルでは、GOTOが到達できないラベルとして処理され、終了しますREMコマンドよりも高速です。)

C:\ something> md cd
C:\ something> echo echo subdir >> cd \ a.bat
C:\ something> md \ a
C:\ something> 。\ cd \ a.bat
subdir

C:\ something> ::サブディレクトリ
C:\ something> cd \ a
C:\ a>から実行された::現在のディレクトリが変更されたため、cdが優先された

更新:さらに実験すると、指定されたディレクトリにピリオドが含まれていない場合にのみ、内部cdコマンドがファイルシステムよりも優先されることがわかりました。そのため、「a.bat」という名前のディレクトリがある場合、「**cd\a.bat**」を実行するとバッチファイルが実行されます。

(ほとんどのディレクトリにはピリオドが含まれていない可能性が高いため)あまり一般的でない動作のこの調査により、調査結果を更新することになりました。これは、ことが判明したCDコマンドは、実際に多くの類似した動作しているコピー私が最初に思ったよりコマンド。

最初はcdコマンドとcopyコマンドが異なる動作をしていると思っていましたが、それは私が提供していた名前のパターンが原因であることがわかりました。それでも、以前の結果を確認し、以前に文書化されたテストは、名前にピリオドと拡張子が含まれる場合と含まれない場合の違いを示すのに役立つと判断しました。そのため、私はまだ古い調査結果を以下に含めています(ほとんど変更されていませんが、いくつかの非常にマイナーな更新があるので、私の言うことは正確です)。

次に、拡張子が使用されていない場合にcdと同じ優先順位(内部コマンドを優先)を使用しないcopyを示す例を示します

C:\ something> echo echo root >> \ try.bat
C:\ something> md copy
C:\ something> echo echoサブディレクトリ>> copy \ try.bat
C:\ something> 。\ copy \ try.batの実行元サブ
ディレクトリサブディレクトリ

C:\ something> copy \ try.bat
サブディレクトリ

C:\ something> ::ハァッ?なぜそれがオーバーライドされてルートから実行されなかったのですか?
C:\ something> ::どうやら、内部コピーコマンドは、サブディレクトリと完全なファイル名のチェックよりも優先されませんでした(ディレクトリに拡張子がない場合、内部cdコマンドが優先されますが)
C:\ something> ::
C:\ some>::別のテスト:
C:\ something> 。\ copy .. \ try.bat
サブディレクトリ

C:\ something> の最後に無駄なピリオドを追加できます。しかし、これはサブディレクトリをチェックしません:
C:\ something> copy .. \ try.bat
        1ファイルがコピーされました。

C:\ something> ::内部コピーコマンドを実行した

私の初期の発見は、これらの結果がコマンドラインシェルが優先権を与えることを示していることを示していました。

  • 内部コマンドの名前の直後にバックスラッシュを指定すると、(内部コピーコマンドの代わりに)ファイルシステムに
  • 内部コマンドの名前の直後にバックスラッシュを指定すると、(ファイルシステムの代わりに)内部cdコマンドに。
  • 内部コマンドの名前の直後にピリオドを指定する場合、(ファイルシステムではなく)内部コピーコマンドに。

これは、copyコマンド(拡張子を含む完全なファイル名)とcdコマンド(ディレクトリ名の一部として拡張子を含まない)の間で動作が一貫していないことを明確に示しています。バックスラッシュを使用する場合、コピーコマンド(完全なファイル拡張子を持つ)は最初にファイルシステムをチェックしますが、cdコマンドはチェックしません(ディレクトリに拡張子が含まれていない場合)。

(更新:最初は、不整合はプログラム間の異なる動作に基づいていると考えました。後で、不整合が存在することを発見しましたが、提供されたパラメーターが原因です。)

実際、これらの箇条書きでさえも、私が言った個々のことをすべて実証しているように見えたとしても、完全に正確ではありません。問題は、箇条書きのリストが完全に正確になるほど正確ではないということです。(これらの箇条書きを比較的簡単に比較し、比較的簡単にチェックできるように、不正確なものを残しました。)

ただし、より正確にするために、最初の箇条書きでは、コマンドラインシェルが優先されることを指摘する必要があります。

  • バックスラッシュを指定するときにファイルシステムに(内部コピーコマンドの代わりに)次に内部コマンドの名前の直後のフルパスの残りの部分

以下は、私がその区別をしている理由を示しています。

C:\ elsewhere> この行に必要なUAC標高をエコー>> \ needext
C:\ elsewhere> この行に必要なUAC標高をエコー>> \ needext.bat
C:\ elsewhere> md。\ copy
C:\ elsewhere> echo @ Echo subdir >> copy \ needext.bat
C:\ elsewhere> 。\ copy \ needext
subdir

C:\ elsewhere> copy \ needext.bat
subdir

C:\ elsewhere> copy \ needext
        1ファイルがコピーされました。

C:\ elsewhere> ::次の行にもUACが必要
C:\ elsewhere> del \ needext
C:\ elsewhere> del \ needext.bat

(内部コピーコマンドが使用されているため、最後のコピーコマンドは\ needextというファイルを探しました。ファイル\ needext.batは、copyという単語を含むコマンドラインで使用されたことがないことを簡単に示すために作成されました。)

この時点で、バックスラッシュを使用すると、(copyコマンドの動作と)矛盾が発生します...

次に、これらのコマンド間に一貫性があることを示します。(つまり、一貫性があります...ええと...一貫性があり、一貫性がない場合があります。)次に示すのは、ピリオドを使用した場合にcdコマンドがcopyコマンドのように動作することです。コピーコマンドは、内部コマンドを使用し、そうCDのコマンドを。

C:\ something> md。\ yetmore

C:\ something> cd。\ yetmore

C:\ something \ yetmore> md。\ md
C:\ something \ yetmore> echo echo subdir >> md \ test.bat
C:\ something \ yetmore> 。\ md。\ test
subdir

C:\ something \ yetmore> md。\ test

C:\ something \ yetmore> md。\ test
サブディレクトリまたはファイル。\ testは既に存在します。

C:\ something \ yetmore> ::このエラーは、内部コマンドを実行したことを示しています。
C:\ something \ yetmore> md .. \ test
C:\ something \ yetmore> md。\ cd
C:\ something \ yetmore> copy。\ md cd
。\ md \ test.bat
        1ファイルがコピーされました。

C:\ something \ yetmore> 。\ cd。\ test
subdir

C:\ something \ yetmore> cd。\ test
C:\ something \ yetmore \ test> ::内部コマンドは1つのピリオドで動作しました
C:\ something \ yetmore \ test> cd ..
C:\ something \ yetmore> 。\ cd .. \ test
subdir

C:\ something \ yetmore> cd .. \ test
C:\ something \ test> ::内部コマンドも2つのピリオドが優先される場合中古

そのため、主にcdコマンドとコピーコマンドに焦点を合わせた最初のテストセッション中に(mddelを少し使用)、実際にファイルシステムに優先権を与えたのは、コピーコマンドのみでした。ファイルシステムは、フルパスを使用する場合のみ優先されていました。

その後のレビューの後、拡張機能を使用する場合、cdコマンドもファイルシステムに優先順位を与えることがわかりました。少なくともこれは、内部コマンドが互いに少し一貫して扱われていることを意味します。ただし、ファイルシステムオブジェクト(ファイルまたはディレクトリ)の名前に基づいて異なる動作を取得することも意味します。これは、ビヘイビアーがいくつかの本当に不明瞭な内部ロジックを使用しているようです。したがって、さまざまなオペレーティングシステムで動作するこの動作を期待することは、おそらく安全ではないと考えられることです。


「記述した動作は、コマンドラインインタープリターの内部のすべてのコマンドで一貫しています。」ipconfigたとえばも動作します。
ジョナスコリッツ

@JonasKöritz:いいえ。コマンド「IPConfig」の直後に(フォワード)スラッシュを付けることができIPCONFIG/ALLます。しかし、それは私が話していたものではありません。「あなたが記述行動(あなたの質問には)」右のコマンド名の後にピリオドを置くの行動でした。私が入力した場合IPConfig.、私は発見されていないコマンドに関するエラーが発生します。同様に(これはあなたが説明していた動作とは関係ありませんが)入力IPCONFIG\ALLすると、作成したカスタム.\IPCONFIG\ALL.BATファイルを実行できます。だから、/年代が同じように扱われていない.か、 `\`
TOOGAM

1
私はあなたの答えを受け入れて、それを作成するのにかかった仕事と研究に感謝します!
ジョナスコリッツ

2
@Calchas簡単なテスト-実行copy.exeまたはcopy.comcmdで試してください。動作しません-実行可能ファイルではありません。
ルアーン

1
@Luann:に関してipconfig、私はあなたの結論に同意しません。この質問は、コマンドラインの最初に入力する内容に関するものです。Windows / DOSはファイル名拡張子で実行可能ファイルを識別するため、拡張子なしで「ipconfig」というプログラムを実行することはできません(Windowsでは、これを許可するUnixとは異なります)。次のコメントに関しては、「Calchas」が誰なのかわかりません。(アットマークを指定すると、通常、ページのどこかに表示されるユーザーの最初の文字は次のようになります。)同意すると、「copy.exe」を実行すると内部copyコマンドが使用されます.exe。(実行できます.\copy.exe
TOOGAM

41

具体的には、コマンド名とその引数はスペースで区切る必要があると想定していますが、これは正しくありません。呼び出しを明確に解釈できる限り、呼び出しは有効です。

この場合、最初の引数が始まる..、コマンド名の一部とすることができないので、cd..単に二つの別々のトークンとして解析されます。

通常、最初の引数はアルファベット文字(パスの先頭など)で始まるため、コマンド名に「にじんで」エラーが発生しますが、これは構文の問題ではありません。セマンティックなものです。

次のような他のコマンドを使用しても、同じ効果が得られますecho

echo...
..

ので、このケースでは、我々は2つだけの期間を取得し、コマンド自体は特別なルールがあり、次のように、:echo

echo .

または、拡張により、これ:

echo.

空行のみを出力します。便利です。どうやら、引数の先頭のピリオドを無視することで実装されているようです。

ねえ、これはDOS / Batchです。正気か?:D


2
それはWindowsのコマンドラインに固有のものですので、私はこれを仮定し、例えばbashはあなたがやるん許可されませんcd..
ジョナスKöritz

47
@JonasKöritz:これは、まったく異なるオペレーティングシステム上のまったく異なるプログラムです。私の自転車cd..もどちらも許可していません:)
オービットでの軽量レース

15
@JonasKöritz:alias cd..='cd ..'
mouviciel

5
@LightnessRacesinOrbit:もともとは、フィルタリングのショートカットだった...他のすべてのディレクトリ内のディレクトリとして表示され、私の知る限りではそれ以上のものをキャッチするために意図されていませんでした。実際、ファイル属性としてモデル化された隠されたものは、ファイル名から暗黙的に従うよりもクリーンなデザインであると考えています。
ジョーイ

4
@joey -私は、より関連性のポイントは、DOSのアプローチは単純だったことはありませんが、それはあることだと思うDOSが許可されていませんでした.ファイル名で、それが意味され、コマンド名の一部であることができなかったため、引数の一部となっている必要があります。UnixシェルのようにDOSがコマンドを引数に分割した場合でも.、コマンド名に無効な文字を入力しても意味がないため、コマンドの後に最初の引数を配置します。
ジュール

19

cd..コマンドが正しいか、それは元のコマンド・インタプリタでそのように定義されたcommand.com後に命名されましたcmd.exe

コマンドインタープリターは、のように特殊文字であるcd..ため、処理方法を知っています。.\


8
主な問題は、構文がどこにも正式に指定されていないため、コマンドが「構文的に間違っている」ことはできないため、プライマリ実装(cmd.exeまたはMS-DOS)がそれを受け入れる場合、それは正しい必要があると思います。
grawity

3
また、CDはプログラムではなく、内部コマンドです。内部コマンドでもあるEchoと同様に、機能するためのスペースは必要ありません。echo.同様に機能し、空の行を出力します。
LPChip

2
など、MD、CDとの同じよう、エコー、どちらか動作しませんechoeの@Overmind
LPChip

2
@JonasKöritzは、.ドロップされませんが、スペースが追加されます。md.testそしてmd .test両方のディレクトリを作成します.test。入力するcd.testcd .test、ディレクトリに変更され.testます。
ダニエル。ノイマン

6
@JonasKöritz:構文がコマンドスペース引数になったことがないからです。
軌道での軽量レース

11

これは後方互換性のハックです。

コマンドラインインタープリターは、CP / Mコマンドインタープリターと後方互換性があるように設計された、元のMSDOSコマンドインタープリターからのコマンドと後方互換性があるように設計されています。CP / MもMSDOSも.ファイル名に使用できません(ファイル名の2つの部分、ベース名と拡張子の間の区切り文字として解釈されました)。これは、(少なくともDOSの初期バージョンでは)コマンドインタープリターが '。'に達した場合にそれを識別できることを意味していました。(実際、ファイル名で違法であった他の文字)は、コマンド名の終わりを渡して、コマンド引数に入りました。これは、DOSとCP / Mの両方で非常に一般的に使用されていました。たとえば、dir/w非常に一般的なコマンドであり、dir /wファイルを水平形式でリストすることと同等です。

最近では、「。」ファイル名に表示できます。これは、コマンドを解析する方法でいくつかの合併症を引き起こすが、シェルは、まだ特定し.、引数の始まりであるとして正確なファイル名の一部ではないことを。これは主に、何百万人ものユーザーがタイピングに慣れてcd..いるかecho.、そのコマンドまたは他の同様のコマンドを含む多数のバッチファイルを持っているために必要です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.