題 為什麼“cd ..”在Windows命令行中有效?


打字時 cd.. 之間沒有空格 cd 和 .. Windows命令提示符將很高興切換到父文件夾。這種行為有解釋嗎?該命令不符合標準格式 command<space>arguments

Working but shouldn't?

另外,為什麼這不會產生一致的結果呢?

echo..


86
2018-06-06 10:32


起源


你的問題的前提似乎被打破了。您是否可以提供任何證據證明這在語法上是錯誤的? - Lightness Races in Orbit
我不認為“命令<space>參數”曾經是 標準 cmd(或其任何前置傳感器)中的格式;考慮例如 dir/a 或類似的VMS語法。 - grawity
cd非常特別。你可以輸入 cd c:\program files 沒有引號,它仍然有效 - phuclv
這是一篇非常有趣的文章,它解釋了Windows shell邏輯的怪癖,以及它可能導致的混亂: thedailywtf.com/articles/The-Core-Launcher - vsz
為什麼 cd.. 工作?因為微軟經歷了明確使其工作的麻煩。 cd 是Windows命令解釋器內置的命令,Microsoft可以讓他們的解釋器做任何他們想做的事情。 (另一個例子, cd 也不需要引用名稱中帶空格的目錄。) - jamesdlin


答案:


正如其他一些答案/評論所指出的那樣,在命令之後必須有空格的想法是不正確的。一個眾所周知的示例是您可以在命令後鍵入正斜杠,而不需要先佔用空格。

然而,還有另一種行為有點不太了解,並允許“cd..“你問的是。這種行為也允許”cd\“ 上班。

您描述的行為與命令行解釋器內部的所有命令一致。如果您有某些符號,包括句點,正斜杠或反斜杠,則檢查先前的字符以查看它們是否是“命令行解釋器”shell(CMD.EXE或其前身COMMAND.COM)內部的命令。 )。

這可以在檢查該單詞是否可以引用文件或子目錄之前完成。這是真的 cd 命令。可悲的是,在製作樣品時,我發現這不會發生 copy 命令,因此結果不一致:它們不一定與所有內部命令相同。我沒有繼續我的搜索也比較(很多)其他命令行 del 和 dir,所以如果你試圖依靠沒有空間的事情,我只是建議你非常小心。

現在,問題還詢問了 迴聲 命令:這是一個不尋常的例外,我認為 echo. 這是DOS專家所熟知的。這可能是有記錄的。這種行為,至少在Win7中 CMD,如果命令以“echo.“,那麼第一個時期就被忽略了。所以,”echo..hi“變成輸出”.hi“這樣做的原因是”echo.“可以用來打印一個空白行。相比之下,使用Unix,你可以通過運行”echo“命令本身。但是,在DOS中,運行”echo“命令本身將輸出當前”迴聲“設置。同樣,DOS對待”Echo *Off*“和”Echo *On*“作為改變當前迴聲設置的特殊值。如果你真的想要打印單詞”Off“, 然後 ”Echo.Off“訣竅(至少在近期版本的微軟版本中) CMD 命令行解釋器。)

所以,至少是 echo 命令有一個半合理的解釋。至於其餘的命令,我曾經認為內部命令具有優先權。但是,當我嘗試進行一些測試時,我發現這實際上是相當不一致的。我通過這裡記錄的一些例子證明了這一點。


這裡有些例子。我確實使用了一個提升的命令提示符,因此UAC不會抱怨我寫入根目錄。這是使用Microsoft Windows 7的CMD.EXE完成的。我懷疑行為可能與其他版本不同,例如舊版MS-DOS版本的COMMAND.COM或其他公司發布的軟件(DR-DOS的COMMAND.COM)。

(這個答案已經很長了,所以我不會包含命令來清理我在文件系統上所做的所有混亂。這裡有一點點清理,但並不多。)

這是一個證明內部命令創建優先級的示例。 (我還演示了使用雙冒號有效地作為註釋的鮮為人知的能力,這在批處理文件中也很有效。從技術上講,在批處理文件中,它被處理為GOTO無法訪問的標籤,並結束比REM命令更快。)

C:\什麼> md cd
C:\什麼> 迴聲 echo subdir >> cd \ a.bat
C:\什麼> md \ a
C:\什麼> \ CD \ a.bat
子目錄

C:\什麼> ::那是從子網運行的
C:\什麼> CD \一
C:\ A> ::那改變了我當前的目錄,所以 光盤 優先考慮

更新: 經過進一步的實驗,我發現了內部 光盤 如果指定的目錄不包含句點,則命令僅優先於文件系統。所以,如果你有一個名為“一隻蝙蝠“,那麼你可以跑”**cd\a.bat**“並且批處理文件將運行。

對不常見行為的探索(因為大多數目錄可能沒有句號)導致我更新我的發現。事實證明, 光盤 命令實際上表現得更像 複製 命令比我最初的想法。

雖然我最初想的是 光盤 和 複製 命令行為不同,我現在想通了,因為我提供的名稱模式。儘管如此,我還是回顧了我之前的結果,並確定我之前記錄的測試確實有助於顯示名稱包含句點和擴展名時發生的情況之間的區別,以及何時不存在。所以,我仍然在下麵包括我的老發現(大多數沒有改變,但有一些非常小的更新,所以我說的是準確的)。


105
2018-06-06 19:43



“您描述的行為與命令行解釋器內部的所有命令一致。” ipconfig 例如也有效。 - Jonas Köritz
@JonasKöritz:不。你可以在命令之後放一個(前進)斜線“IPConfig能“那會有用,例如 IPCONFIG/ALL。然而,這不是我所說的。 “您描述的行為“(在您的問題中)是在命令名稱後面放置句點的行為。如果我輸入 IPConfig. 然後我收到有關未找到命令的錯誤。同樣(雖然這與您描述的行為無關),如果我輸入 IPCONFIG\ALL然後我可以運行自定義 .\IPCONFIG\ALL.BAT 我做的文件。所以 /沒有像對待那樣 . 或者`\` - TOOGAM
我將接受你的回答,欣賞它創造它所做的工作和研究! - Jonas Köritz
@Calchas簡單測試 - 嘗試執行 copy.exe 要么 copy.com 在cmd。它不起作用 - 它不是可執行文件。 - Luaan
@Luann:關於 ipconfig,我不同意你的結論。這個問題是關於命令行開頭的內容。 Windows / DOS通過文件擴展名識別可執行文件,因此您無法在沒有擴展名的情況下運行名為“ipconfig”的程序(在Windows中,與允許此操作的Unix不同)。關於下一個評論,我不知道“Calchas”是誰。 (當您指定at符號時,以下通常是顯示在頁面其他位置的用戶的第一個字符。)我同意,運行“copy.exe“將使用內部 copy 命令(和通過 .exe)。 (你可以跑 .\copy.exe) - TOOGAM


您假設命令名稱及其參數必須用空格分隔,具體而言,但事實並非如此。只要可以明確地解釋調用,調用就是有效的。

在這種情況下,第一個參數以。開頭 . 和 . 不能成為命令名的一部分,所以 cd 和 .. 簡單地解析為兩個單獨的標記。

通常,您的第一個參數將以字母字符開頭(例如路徑的開頭),因此它會“滲透”到您的命令名中並導致錯誤......但這不是語法問題。這是一個語義問題。

您可以在使用其他命令時看到相同的效果,包括 echo

echo...
..

在這種情況下,我們只得到兩個時期,因為 echo 命令本身有一個特殊的規則,以下內容:

echo .

或者,通過擴展,這個:

echo.

只輸出一個空行。這很方便。顯然它是通過忽略論證中的領先時期來實現的。

嘿,這是DOS / Batch。你想要理智嗎? :d


41
2018-06-06 11:35



我假設這是因為它是Windows命令行所特有的,例如bash不允許你這樣做 cd.. - Jonas Köritz
@JonasKöritz:在完全不同的操作系統上,這是一個完全不同的程序。我的自行車不允許 cd.. 要么:) - Lightness Races in Orbit
@JonasKöritz: alias cd..='cd ..' - mouviciel
@LightnessRacesinOrbit:最初它是過濾掉的捷徑 . 和 .. 它在所有其他目錄中顯示為目錄,據我所知,從來沒有打算捕獲更多。我實際上認為隱藏模型作為文件屬性建模比使用文件名隱含的隱藏設計更清晰。 - Joey
@joey - 我認為更重要的一點不是DOS方法更簡單,就是這樣 DOS不允許 . 在文件名中,這意味著它 不能成為命令名稱的一部分 因此 一定是參數的一部分。即使DOS已經將命令劃分為Unix shell中的參數,它仍然會放置一個 . 在命令進入第一個參數之後,因為將無效字符放入命令名稱是沒有意義的。 - Jules


cd..命令是正確的,它的定義與原始命令解釋器中的命令相同 command.com後來被命名 cmd.exe

命令解釋器知道如何處理 cd..因為 . 是一個特殊的角色,就像 \


19
2018-06-06 10:43



我想主要問題是命令不能“語法不正確”,因為語法 在任何地方都沒有正式指定,所以如果主要實現(cmd.exe和/或MS-DOS)接受它,那麼它必須是正確的。 - grawity
此外,CD不是程序,而是內部命令。與Echo類似,它也是一個內部命令,它不需要有空間來工作。 echo. 效果也一樣,會打印一個空行。 - LPChip
@Overmind echoe也不會工作,所以它與cd,echo,md等一樣。 - LPChip
@JonasKöritz, . 不會掉落但只添加一個空格。 md.test 和 md .test 都創建目錄 .test。打字 cd.test 和 cd .test 將更改為目錄 .test。 - daniel.neumann
@JonasKöritz:因為語法從來就不是命令空間參數。 - Lightness Races in Orbit


這是一個向後兼容的黑客攻擊。

命令行解釋器設計為向後兼容來自原始MSDOS命令解釋器的命令,該命令解釋器設計為向後兼容CP / M命令解釋器。 CP / M和MSDOS都不允許 . 在文件名中(它被解釋為文件名的兩個部分之間的分隔符,基本名稱和擴展名)。這意味著(至少對於早期版本的DOS),命令解釋器可以識別它是否達到“。” (或者確實是文件名中非法的任何其他字符)它傳遞了命令名稱的末尾並進入命令參數。這在DOS和CP / M中都很常用 - 例如, dir/w 是一個非常常見的命令,相當於 dir /w 意思是以橫向格式列出文件。

如今,'。'可以出現在文件名中。這導致瞭如何解析命令的一些複雜性,但shell 仍然 識別出一個 . 這不是確切文件名的一部分,因為它是參數的開頭。這很有必要,因為數百萬用戶已經習慣於打字 cd.. 或者有大量包含該或的批處理文件 echo. 或任何數量的其他類似命令。


11
2018-06-06 14:55