Neden “cd ..” Windows komut satırında çalışıyor?


86

Yazarken cd..arasındaki boşluk bırakmadan cdve ..Windows komut istemine mutlu üst klasör geçer. Bu davranış için bir açıklama var mı? Komut standart biçimini izlemiyorcommand<space>arguments

Çalışıyor ama yapmamalı mıyım?

Ayrıca, bu neden tutarlı sonuçlar vermiyor?

Eko..


24
Sorunuzun öncülü kırılmış gibi görünüyor. Bunun sözdizimsel olarak yanlış olduğu iddiasına dair herhangi bir kanıt sunabilir misin?
Orbit'teki Hafiflik Yarışları,

13
"Command <boşluk> argümanlarının" hiç cmd (veya öncekilerden herhangi birinin) standart formatı olduğunu sanmıyorum ; örneğin dir/aveya benzer VMS sözdizimini göz önünde bulundurun .
Grawity

6
CD çok özel. cd c:\program filesTırnak işaretleri olmadan yazabilirsiniz ve hala çalışır
phuclv

20
İşte Windows kabuk mantık tuhaflıklar açıklayan bir çok eğlenceli makale olduğunu ve nelerin neden olabileceğini kargaşa: thedailywtf.com/articles/The-Core-Launcher
vsz

3
Neden cd..çalışıyor Çünkü Microsoft açıkça çalışmasını sağlamakta zorlandı. cdWindows'un komut tercümanına yerleştirilmiş bir komuttur ve Microsoft tercümanını istediklerini yapar. (Başka bir örnek olarak, cdadında boşluk bulunan dizinlerin etrafında alıntı yapmak da gerekmez.)
jamesdlin

Yanıtlar:


106

Diğer cevapların / yorumların notunda olduğu gibi, komuttan sonra bir boşluk olması gerektiği fikri doğru değildir. Bilinen bir örnek, önce boşluğa gerek duymadan komuttan sonra eğik çizgi yazabilmenizdir.

Ancak, biraz daha az anlaşılan ve cd..sorduğunuz " " ifadesine izin veren başka bir davranış var. Bu davranış aynı zamanda " cd\" çalışmasını sağlar.

Tanımladığınız davranış, komut satırı yorumlayıcısının içindeki tüm komutlar için tutarlıdır. Bir nokta, eğik çizgi veya ters eğik çizgi dahil belirli simgeleriniz varsa, önceki karakterler "komut satırı tercümanı" kabuğuna (CMD.EXE veya öncül COMMAND.COM) bir komut olup olmadığını görmek için kontrol edilir. ).

Bu, kelimenin bir dosyaya mı yoksa alt dizine mi başvuracağını kontrol etmeden önce yapılabilir. Bu cdkomut için geçerlidir . Trajik bir şekilde, bir örnekleme yaparken bunun copykomutla gerçekleşmediğini öğrendim, bu yüzden sonuçlar tutarsız: tüm iç komutlarla aynı olması gerekmez. Aramaya devam ettim (çok) diğer komut satırını da karşılaştırdım delve dirbu yüzden, boşluk olmadan ne olduğuna güvenmeye çalışırsanız çok dikkatli olmanızı öneririm.

Şimdi, soru yankı komutunu da sordu : Bu olağandışı bir istisnadır, bence echo.DOS uzmanları tarafından oldukça iyi bilinmektedir. Bu muhtemelen belgelenmiştir. Davranış, Win7 en en az CMD komut "ile başlıyorsa olmasıdır echo.", daha sonra ilk periyodu göz ardı edilir. Böylece, " echo..hi" , " " çıktısına dönüşür .hi. Bunun nedeni, " echo." boş bir satır yazdırmak için kullanılabilecek olmasıdır. Bunun aksine, Unix ile bunu " echo" komutunu tek başına çalıştırarak yapabilirsiniz . Ancak, DOS'ta " echo" komutunu kendi başına çalıştırmak geçerli " echo " ayarını verir. Benzer şekilde, DOS " Echo *Off*" ve "işlemlerini yaparEcho *On*"geçerli yankı ayarını değiştiren özel değerler olarak." Off" kelimesini gerçekten yazdırmak istiyorsanız ," Echo.Off"hile yapar (en azından Microsoft'un CMD komut satırı yorumlayıcısının yeterince yeni sürümleriyle ).

Dolayısıyla, en azından echokomutun makul bir açıklaması var. Kalan komutlara gelince, iç komutların önceliği olduğunu düşünürdüm. Ancak bazı testler yapmaya çalıştığımda, bunun aslında oldukça tutarsız olduğunu gördüm. Bunu burada belgelediğim bazı örneklerle gösteriyorum.


İşte bazı örnekler. Yükseltilmiş bir komut istemi kullandım, böylece UAC benimle ilgili kök dizine yazma konusunda yanılmazdı. Bu, Microsoft Windows 7'nin CMD.EXE ile yapıldı. Davranışların, eski MS-DOS sürümlerinden gelen COMMAND.COM veya diğer şirketler tarafından yayınlanan yazılımlar (DR-DOS COMMAND.COM) gibi diğer sürümlerle farklı olabileceğinden şüpheleniyorum.

(Bu cevap zaten oldukça uzun, bu yüzden dosya sistemimdeki tüm karışıklığı temizleme komutlarını eklemiyorum. Küçük bir temizleme işlemi var, ancak çok fazla değil.)

İşte iç komutun öncelik oluşturduğunu kanıtlayan bir örnek. (Ayrıca, etkili bir yorum yapmak için çift kolon kullanabilmek için az bilinen bir yeteneği de gösteriyorum, toplu iş dosyalarında da iyi çalışıyor. Teknik olarak, toplu iş dosyalarında GOTO tarafından erişilemeyen bir etiket olarak işleniyor ve bitiyor REM komutundan daha hızlı olması.)

C: \ bir şey> md cd
C: \ bir şey> echo yankı altdizin >> cd \ a.bat
C: \ bir şey> md \ a
C: \ bir şey> . \ Cd \ a.bat
alt dizin

C: \ bir şey> :: Yani subdir kaçtı
C: \ şey> a \ cd
C: \ a> :: benim şimdiki dizini değişti, o yüzden bu cd öncelik aldı

Güncelleme: Daha fazla denemede, belirtilen cd bir nokta içermiyorsa , dahili cd komutunun sadece dosya sistemi üzerinde önceliğe sahip olduğunu buldum . Yani " a.bat " adında bir dizininiz varsa, "" komutunu çalıştırabilirsiniz **cd\a.bat**ve toplu iş dosyası çalışacaktır.

Daha az yaygın davranışın bu şekilde keşfedilmesi (çoğu dizin muhtemelen içinde dönemler olmadığı için) bulgularımı güncellememe neden oldu. Cd komutunun aslında copy komutuna başlangıçta düşündüğümden daha fazla benzer davrandığı ortaya çıktı .

Başlangıçta cd ve copy komutlarının farklı davrandıklarını düşünmeme rağmen , bunun şimdi sağladığım adların modelinden kaynaklandığını anladım. Yine de, önceki sonuçlarımı gözden geçirdim ve daha önce belgelenen testlerimin, bir ad bir süre ile bir uzantı içerdiğinde ve ne zaman olmadığı ile ne olduğu arasındaki farkın bir kısmını göstermeye yardımcı olduğunu belirledim. Bu nedenle, hala daha eski bulgularımı aşağıya ekliyorum (çoğunlukla değişmemiş, ancak bazı çok küçük güncellemeler ile söylediklerim doğru).

Uzatma kullanılmadığında , kopyayı tam yolla gösteren bir örnek (aynı komutu kullanmadan) cd ile aynı önceliği kullanmaz :

C: \ bir şey> yankı eko kökü >> \ try.bat
C: \ bir şey> md kopya
C: \ bir şey> yankı eko alt dizini >> copy \ try.bat
C: \ bir şey> . \ Copy \ try.bat alt
dizini

C: \ something> copy \ try.bat
alt dizini

C: \ something> :: Huh? Bu neden geçersiz kılındı ​​ve kökten çalıştırılmadı?
C: \ something> :: Görünüşe göre, dahili copy komutu, bir alt dizinin ve tam dosya adının kontrolü üzerinde önceliğe sahip değildi (dahili cd komutu, dizinde bir uzantı olmadığında öncelikli olsa bile )
C: \ something> ::
C: \ bir şey>:: Başka bir test:
C: \ something> . \ Copy .. \ try.bat
alt dizinindeki

C: \ something> :: Tamam, işe yaramaz dönemler ekleyebilirim . Ancak bu, alt dizini kontrol etmeyecektir:
C: \ something> copy .. \ try.bat
        1 dosya kopyalandı.

C: \ something> :: Dahili kopya komutunu çalıştırdı

İlk bulgularım, bu sonuçların komut satırı kabuğunun öncelik verdiğini gösterdiğini belirtti:

  • iç komutun adından hemen sonra bir ters eğik çizgi belirlerken dosya sistemine (dahili kopya komutu yerine )
  • iç komutun adından hemen sonra ters eğik çizgi belirlerken , iç cd komutuna (dosya sistemi yerine).
  • Dahili komutun adından hemen sonra bir süre belirlerken , dahili kopyalama komutuna (dosya sistemi yerine).

Bu açıkça, davranışın copy komutu (bir uzantı içeren bir tam dosya adıyla) ve cd komutu (dizin adının bir parçası olarak bir uzantı olmadan ) arasında tutarlı olmadığını açıkça göstermektedir . Bir ters eğik çizgi kullanılırken, ilk önce dosya sistemi denetlenecek , kopya komutu (tam dosya adı uzantısına sahip), ancak cd komutu (dizin bir uzantı içermiyorsa ) denetlemez .

(Güncelleme: İlk başta tutarsızlığın programlar arasındaki farklı davranışlara dayandığını düşündüm. Daha sonra tutarsızlığın var olduğunu ancak sağlanan parametrelerden daha fazla kaynaklandığını gördüm.)

Aslına bakarsanız, bu madde işaretleri bile tam olarak doğru değil, söylediğim her şeyi gösterdiğim halde. Sorun şu ki, madde işareti listesinin tamamen doğru olması için yeterince kesin değil. (Mermi noktalarının nispeten kolay bir şekilde karşılaştırılmasını ve nispeten kolay bir şekilde kontrol edilebilmesini sağlamak için işleri kesin olarak bıraktım.)

Ancak, daha doğru olması için, ilk madde işaret noktası komut satırı kabuğunun öncelik verdiğine işaret etmelidir:

  • Bir ters eğik çizgi belirlerken dosya sistemine (iç kopya komutu yerine ) ve ardından tam yolun geri kalanını , iç komutun adından hemen sonra

Aşağıdakiler neden bu ayrımı yaptığımı gösterecektir:

C: \ başka bir yerde> bu satır için gerekli yankı UAC yüksekliği >> \ needext
C: \ başka bir yerde> eko UAC yüksekliği bu satır için gerekli >> \ needext.bat
C: \ başka bir yerde> md. \ Copy
C: \ başka bir yerde> echo @ yankı subdir >> kopya \ needext.bat
C: \ başka yerde> . \ copy \ needext
altdiz

C: \ başka yerde> \ needext.bat kopyalamak
altdiz

C: \ başka yerde> kopya \ needext
        1 dosya (lar) kopyalandı.

C: \ başka yerde> :: UAC ayrıca sonraki satırlar için gerekli
C: \ başka yerde> del \ needext
C: \ elsewhere> del \ needext.bat

( Dahili kopya komutu kullanıldığından son kopya komutunun \ needext adındaki dosyayı aradığına dikkat edin . \ Needext.bat dosyası yalnızca kopya kelimesini içeren komut satırları tarafından hiç kullanılmadığını kolayca göstermek için oluşturuldu. .)

Bu noktada, ters eğik çizgi kullanıldığında ( copy komutunun davranışıyla) bazı tutarsızlıklar tespit ettim ...

Sonra bu komutlar arasında bir miktar tutarlılık olduğunu göstereceğim. (Öyleyse, tutarlılık var ... um ... bazen. Tutarsızlıkla sadece tutarlılığımız olabilir.) Bir sonraki göstereceğimde cd komutunun kopya komutu gibi davranmasıdır . Kopya komutu iç komutu kullanır ve yapar cd komutu.

C: \ şey> md \ yetmore.

C: \ şey> cd \ yetmore.

C: \ şey \ yetmore> md \ md.
C: \ şey \ yetmore> yankı yankı altdiz >> md \ test.bat
C: \ şey \ yetmore> \ mD \ testi..
altdiz

C: \ şey \ yetmore> md \ testi.

C: \ şey \ yetmore> . md \ sınamak
bir alt dizin veya dosya \ testi zaten var..

C: \ bir şey \ henüz daha>> Bu hata, dahili komutu çalıştırdığımızı gösterir.
C: \ bir şey \ henüz daha fazla> md .. \ test
C: \ bir şey \ henüz daha fazla> md. \ Cd
C: \ bir şey \ yine de> kopyalayın. \ Md cd
. \ Md \ test.bat
        1 dosya kopyalandı.

C: \ bir şey \ yeteri kadar> . \ Cd. \ Test
alt

dizini C: \ bir şey \ yetkinlik> cd. \ Test
C: \ bir şey \ yetkinlik \ test> :: iç komut bir dönem
C: \ bir şey \ yetti \ test> cd ..
C: \ bir şey \ yeteri kadar> . \ cd .. \ test
alt

dizini C: \ bir şey \ yetişme> cd .. \ test
C: \ bir şey \ test> :: iç komut da iki periyot olduğunda önceliği aldı Kullanılmış

Yani, çoğunlukla odaklanmış ilk test oturumu sırasında cd ve kopyalama (bazı ek kullanımı ile komutları md ve biraz del , gerçekten dosya sistemi almak önceliği oldu vardı sadece zaman) kopya daha sonra komuta ve dosya sistemi sadece tam yolu kullanırken önceliği kullanıyordu.

Daha sonra yapılan incelemelerden sonra, bir uzantı kullanırken cd komutunun dosya sistemi önceliği verdiğini de buldum . En azından bu, iç komutların birbirleriyle biraz daha tutarlı davrandığı anlamına gelir. Ancak, aynı zamanda dosya sistemi nesnelerinin (dosya veya dizin) adlarını temel alan farklı davranışlar elde ettiğimiz anlamına gelir. Davranış, bazı gerçekten, gerçekten karanlık bir iç mantık kullanıyor gibi görünüyor. Bu nedenle, farklı işletim sistemlerinde çalışmak için bu davranışa güvenmek, muhtemelen güvenli olmayacağını düşündüğüm bir şey.


"Tanımladığınız davranış, komut satırı yorumlayıcısının içindeki tüm komutlar için tutarlıdır." ipconfigörneğin, aynı zamanda çalışır.
Jonas Köritz

@ JonasKöritz: Hayır. " IPConfig " komutundan hemen sonra bir eğik çizgi koyabilirsiniz ve bu işe yarar IPCONFIG/ALL. Ancak bahsettiğim şey bu değildi. “ Tanımladığınız davranış ” (sorunuza) komut adından hemen sonra bir nokta koyma davranışıydı. Eğer IPConfig.yazarsam, bulunmayan bir komutla ilgili bir hata alıyorum. Benzer şekilde (bu tanımladığınız davranışla ilgili olmasa da), yazarsanız IPCONFIG\ALLyazdığım özel bir .\IPCONFIG\ALL.BATdosyayı çalıştırabilirim . Öyle /muamele görmüyor .ya da `\`
TOOGAM

1
Oluşturduğunuz çalışma ve araştırmayı takdir etmek için cevabınızı kabul ediyorum!
Jonas Köritz

2
@Calchas Basit test - yürütmeyi copy.exeya copy.comda cmd yapmayı deneyin . Çalışmıyor - bir çalıştırılabilir değil.
Luaan

1
@Luann: ile ilgili olarak ipconfig, senin sonucuna katılmıyorum. Bu soru, komut satırının başında yazılanlarla ilgilidir. Windows / DOS, yürütülebilir dosyaları dosya adı uzantısıyla tanımlar; bu nedenle, uzantı olmadan "ipconfig" adlı bir programı çalıştıramazsınız (Windows'ta buna izin veren Unix'in aksine). Bir sonraki yorum ile ilgili olarak, "Calchas" ın kim olduğunu bilmiyorum. (Bir işaret belirttiğinde, aşağıdakiler genellikle sayfada başka bir yerde gösterilen kullanıcının ilk karakterleridir.) Kabul ediyorum, " copy.exe" copykomutunu çalıştırmak dahili komutu (ve iletir .exe) kullanacaktır . ( .\copy.exe
Koşabilirsin

41

Bir komut adının ve argümanlarının, özellikle boşlukla ayrılması gerektiğini varsayarsınız, ancak bu doğru değildir. Başvuru açıkça yorumlanabildiği sürece, başvuru geçerlidir.

Bu durumda, ilk argüman ile başlar .ve .komut adının bir parçası olamaz, bu yüzden cdve ..sadece iki ayrı jeton olarak çözümlenir.

Genellikle, ilk argümanınız alfabetik bir karakterle başlayacaktır (örneğin yolun başlangıcı), bu nedenle komut adınıza "sızacak" ve bir hataya neden olacak… ancak bu bir sözdizimi sorunu değil. Anlamsal olanı.

Aynı efekti işyerinde aşağıdakiler de dahil olmak üzere diğer komutlarla görebilirsiniz echo:

echo...
..

Çünkü bu durumda, sadece iki dönemleri olsun komut kendisi özel bir kural vardır aşağıdaki böylece:echo

echo .

veya, uzantı olarak, bu:

echo.

sadece boş bir satır çıkarır. Bu bir kolaylık. Görünüşe göre argümandaki lider bir dönemi göz ardı ederek uygulandı.

Hey, bu DOS / Toplu. Akıl sağlığı ister misin? : D


2
Bunu Windows komut satırına özgü olduğundan, örneğin cd..
bash'ın

47
@ JonasKöritz: Tamamen farklı bir işletim sisteminde tamamen farklı bir program. Bisikletim cd..ikisine de izin vermiyor :)
Orbit'teki Hafiflik Yarışları 11

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

5
@LightnessRacesinOrbit: Aslen filtrelemenin kestirme bir yoluydu .ve ..diğer tüm dizinlerde dizinler olarak görünüyordu ve bildiğim kadarıyla hiçbir zaman bundan daha fazlasını yakalamak niyetinde değildi. Aslında dosya özniteliği olarak modellenmiş gizliliği, dosya adından tam olarak takip etmekten daha temiz bir tasarım olarak görüyorum.
Joey,

4
@joey - Ben öyle olduğunu, daha alakalı noktası DOS yaklaşımı daha basit olduğunu olmadığını düşünüyorum DOS izin vermedi .dosya adlarını içinde anlama geldiğini, hangi bir komut adının bir parçası olamazdı bu nedenle argüman bir parçası olmalı . DOS, komutu Unix kabukları gibi argümanlara bölse bile, .komutun arkasına geçersiz bir karakter koymak mantıklı olamayacağından, ilk argümana komuttan sonra yine de koyar.
Jules

19

cd..Komut doğruysa ve orijinal komut yorumlayıcısı böyle tanımlandı command.comsonradan seçildi cmd.exe.

Komut yorumcusu nasıl işleneceğini bilir cd.., çünkü .tıpkı tıpkı özel bir karakterdir \.


8
Asıl mesele, komutun sözdizimi herhangi bir yerde resmen belirtilmediği için "sözdizimsel olarak yanlış" olamamasıdır , bu nedenle, birincil uygulama (cmd.exe ve / veya MS-DOS) kabul ederse, doğru olması gerekir.
Grawity

3
Ayrıca, CD bir program değil, dahili bir komuttur. Aynı zamanda içsel bir komut olan Echo'ya benzer şekilde çalışması için bir alana sahip olması gerekmez. echo.aynı şekilde çalışır, bu da boş bir satır yazdırır.
LPChip,

2
@ Aşırı echoe da çalışmayacak, bu yüzden cd, echo, md, vb.
İle aynıdır

2
@ JonasKöritz, .düşürülmedi, ancak sadece bir boşluk eklendi. md.testve md .testher ikisi de dizini oluşturur .test. Yazarak cd.testve cd .testdizine değişecektir .test.
daniel.neumann

6
@ JonasKöritz: Çünkü sözdizimi hiçbir zaman komut-alanı-argümanları olmadı.
Orbit'teki Hafiflik Yarışları,

11

Geriye dönük bir uyumluluk hack.

Komut satırı yorumlayıcısı, CP / M komut yorumlayıcısı ile geriye doğru uyumlu olacak şekilde tasarlanan orijinal MSDOS komut yorumlayıcısının komutları ile geriye dönük olarak uyumlu olacak şekilde tasarlanmıştır. Ne CP / M ne de MSDOS .bir dosya adına izin vermedi (dosya adının iki kısmı, taban adı ve uzantı arasında bir ayırıcı olarak yorumlandı). Bunun anlamı (en azından DOS'un ilk sürümleri için), komut yorumlayıcısının '.' (ya da dosya isminde yasadışı olan başka bir karakter) komut adının sonundan geçti ve komut argümanlarına girdi. Bu, hem DOS hem de CP / M'de oldukça yaygın bir şekilde kullanılıyordu - örneğin, dosyaları yatay biçimde listelemek için dir/weşdeğer olan çok yaygın dir /wbir komuttu.

Şu günlerde, '.' dosya isimlerinde görünebilir. Bu komutların nasıl ayrıştırılacağı konusunda bazı komplikasyonlara neden olmakla birlikte, kabuk hala. bir tam dosya adının parçası olmayan argümanların başlangıcı olarak tanımlamaktadır . Bu, büyük ölçüde gereklidir, çünkü milyonlarca kullanıcı, cd..bu ya echo.da herhangi bir sayıda başka benzer komutu içeren çok sayıda toplu iş dosyasını yazmak ya da çok sayıda toplu iş dosyasına sahip olmak için kullanıldı .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.