Mengapa "cd .." bekerja di baris perintah Windows?


86

Saat mengetik cd..tanpa spasi di antara cddan ..prompt perintah Windows dengan senang hati akan beralih ke folder induk. Apakah ada penjelasan untuk perilaku ini? Perintah tidak mengikuti format standarcommand<space>arguments

Bekerja tetapi tidak?

Juga, mengapa ini tidak menghasilkan hasil yang konsisten?

gema..


24
Premis pertanyaan Anda tampaknya rusak. Bisakah Anda memberikan bukti untuk klaim Anda bahwa ini secara sintaksis salah?
Lightness Races in Orbit

13
Saya tidak berpikir "perintah <spasi> argumen" pernah menjadi format standar dalam cmd (atau salah satu dari pendahulunya); pertimbangkan misalnya dir/aatau sintaks VMS serupa.
grawity

6
cd sangat istimewa. Anda dapat mengetik cd c:\program filestanpa tanda kutip dan masih berfungsi
phuclv

20
Berikut ini adalah artikel yang sangat menghibur yang menjelaskan keanehan dari logika shell Windows, dan apa
akibatnya

3
Kenapa cd..berhasil? Karena Microsoft mengalami kesulitan membuatnya bekerja secara eksplisit. cdadalah perintah yang dibangun ke dalam interpreter perintah Windows, dan Microsoft dapat membuat interpreter mereka melakukan apa pun yang mereka inginkan. (Sebagai contoh lain, cdjuga tidak perlu mengutip direktori dengan spasi dalam nama.)
jamesdlin

Jawaban:


106

Seperti yang dicatat oleh beberapa jawaban / komentar lain, gagasan bahwa harus ada spasi setelah perintah tidak benar. Contoh terkenal adalah bahwa Anda dapat mengetikkan garis miring setelah perintah, tanpa perlu spasi terlebih dahulu.

Namun, ada perilaku lain yang sedikit kurang dipahami, dan memungkinkan " cd.." yang Anda tanyakan. Perilaku ini juga memungkinkan " cd\" bekerja.

Perilaku yang Anda gambarkan konsisten untuk semua perintah internal ke juru baris perintah. Jika Anda memiliki simbol tertentu, termasuk titik, garis miring, atau garis miring terbalik, maka karakter sebelumnya diperiksa untuk melihat apakah mereka adalah perintah yang internal ke shell "command line interpreter" (CMD.EXE atau pendahulunya COMMAND.COM ).

Ini dapat dilakukan sebelum memeriksa apakah kata tersebut merujuk pada file atau subdirektori. Itu benar untuk cdperintah. Tragisnya, ketika membuat sampel, saya menemukan bahwa ini tidak terjadi dengan copyperintah, sehingga hasilnya tidak konsisten: mereka tidak harus sama dengan semua perintah internal. Saya tidak melanjutkan pencarian saya untuk juga membandingkan (banyak) baris perintah lainnya deldan dir, jadi saya sarankan untuk sangat berhati-hati jika Anda mencoba untuk mengandalkan apa yang terjadi tanpa spasi.

Sekarang, pertanyaannya juga ditanyakan tentang perintah echo : Ini adalah pengecualian yang tidak biasa, karena menurut saya echo.cukup terkenal oleh para pakar DOS. Ini mungkin didokumentasikan. Perilaku, setidaknya dalam CMD Win7 , adalah bahwa jika perintah dimulai dengan " echo.", maka periode pertama diabaikan. Jadi, " echo..hi" berubah menjadi output dari " .hi". Alasannya adalah agar " echo." dapat digunakan untuk mencetak baris kosong. Sebaliknya, dengan Unix, Anda dapat melakukan ini hanya dengan menjalankan perintah " echo" dengan sendirinya. Namun, di DOS, menjalankan perintah " echo" dengan sendirinya akan menghasilkan pengaturan " gema " saat ini . Demikian pula, DOS memperlakukan " Echo *Off*" dan "Echo *On*"sebagai nilai khusus yang mengubah pengaturan gema saat ini. Jika Anda benar-benar ingin mencetak kata" Off"," Echo.Off"lakukan triknya (setidaknya dengan versi terbaru dari interpreter baris perintah CMD Microsoft .)

Jadi, setidaknya echoperintah memiliki penjelasan semi-wajar. Adapun perintah yang tersisa, saya dulu berpikir bahwa perintah internal memiliki prioritas. Namun, ketika saya mencoba melakukan beberapa tes, saya menemukan bahwa sebenarnya agak tidak konsisten. Saya menunjukkan ini melalui beberapa contoh yang saya dokumentasikan di sini.


Berikut ini beberapa contohnya. Saya memang menggunakan prompt perintah yang ditinggikan, sehingga UAC tidak akan mengeluh tentang saya menulis ke direktori root. Ini dilakukan dengan CMD.EXE Microsoft Windows 7. Saya menduga perilaku mungkin berbeda dengan versi lain, seperti COMMAND.COM dari versi MS-DOS yang lebih lama, atau perangkat lunak yang dirilis oleh perusahaan lain (COMMAND.COM DR-DOS).

(Jawaban ini sudah cukup lama, jadi saya tidak termasuk perintah untuk membersihkan semua kekacauan yang saya buat pada sistem file saya. Ada sedikit pembersihan, tapi tidak banyak.)

Berikut adalah contoh yang membuktikan bahwa perintah internal menciptakan prioritas. (Saya juga menunjukkan kemampuan yang agak kurang dikenal untuk menggunakan titik dua untuk secara efektif menjadi komentar, yang juga berfungsi dengan baik dalam file batch. Secara teknis, dalam file batch, itu diproses sebagai label yang tidak dapat dijangkau oleh GOTO, dan berakhir lebih cepat dari perintah REM.)

C: \ sesuatu> md cd
C: \ sesuatu> gema subdir >> cd \ a.bat
C: \ sesuatu> md \ a
C: \ sesuatu> . \ Cd \ a.bat
subdir

C: \ sesuatu> :: Itu berlari dari subdir
C: \ something> cd \ a
C: \ a> :: Itu mengubah direktori saya saat ini, jadi cd didahulukan

Pembaruan: Setelah percobaan lebih lanjut, saya menemukan bahwa perintah cd internal hanya diutamakan di atas sistem file jika direktori yang ditentukan tidak termasuk periode. Jadi jika Anda memiliki direktori bernama " a.bat ", maka Anda dapat menjalankan " **cd\a.bat**" dan file batch akan berjalan.

Eksplorasi perilaku yang kurang umum ini (karena sebagian besar direktori mungkin tidak memiliki periode di dalamnya) mendorong saya untuk memperbarui temuan saya. Ternyata perintah cd sebenarnya berperilaku lebih mirip dengan perintah salin daripada yang saya pikir sebelumnya.

Walaupun saya awalnya berpikir perintah cd dan copy berbeda, saya sekarang tahu itu karena pola nama yang saya sediakan. Namun, saya meninjau hasil saya sebelumnya, dan memastikan bahwa tes saya yang terdokumentasi sebelumnya membantu menunjukkan beberapa perbedaan antara apa yang terjadi ketika sebuah nama menyertakan periode dan ekstensi, dan ketika itu tidak. Jadi, saya masih memasukkan temuan lama saya di bawah ini (kebanyakan tidak berubah, tetapi dengan beberapa pembaruan yang sangat kecil sehingga apa yang saya katakan akurat).

Berikut ini adalah contoh yang memperlihatkan salinan , dengan path lengkap, tidak menggunakan prioritas yang sama (mendukung perintah internal) seperti cd ketika tidak ada ekstensi yang digunakan:

C: \ sesuatu> echo echo root >> \ try.bat
C: \ something> md copy
C: \ something> subdirektori echo echo >> salin \ try.bat
C: \ something> . \ Copy \ try.bat dijalankan dari subdirektori
subdirektori

C: \ something> copy \ try.bat
subdirektori

C: \ something> :: Hah? Mengapa itu tidak menggantikan dan lari dari root?
C: \ something> :: Rupanya, perintah copy internal tidak memiliki prioritas di atas pemeriksaan untuk subdirektori dan nama file lengkap (meskipun perintah cd internal mengambil prioritas, ketika direktori tidak memiliki ekstensi)
C: \ sesuatu> ::
C: \ sesuatu>:: Tes lain: Saya dapat menambahkan periode yang tidak berguna di akhir
C: \ something> . \ Copy .. \ try.bat
subdirektori

C: \ something> :: Oke, bagus. Tetapi kemudian ini tidak akan memeriksa subdirektori:
C: \ something> salin .. \ try.bat
        1 file disalin.

C: \ something> :: Itu menjalankan perintah salin internal

Temuan awal saya menunjukkan bahwa hasil ini menunjukkan bahwa shell baris perintah memberikan prioritas:

  • ke sistem file (bukan perintah salin internal ) ketika menentukan backslash tepat setelah nama perintah internal
  • ke perintah cd internal (bukan sistem file) ketika menentukan backslash tepat setelah nama perintah internal.
  • ke perintah copy internal (bukan sistem file) ketika menentukan periode tepat setelah nama perintah internal.

Ini jelas menunjukkan bahwa perilaku tidak konsisten antara perintah salin (dengan nama file lengkap termasuk ekstensi) dan perintah cd (tanpa ekstensi sebagai bagian dari nama direktori). Saat menggunakan backslash, perintah copy (dengan ekstensi nama file lengkap) akan memeriksa sistem file terlebih dahulu, tetapi perintah cd tidak akan (jika direktori tidak mengandung ekstensi).

(Pembaruan: Awalnya, saya pikir inkonsistensi didasarkan pada perilaku yang berbeda antara program. Kemudian, saya menemukan bahwa inkonsistensi memang ada, tetapi lebih disebabkan oleh parameter yang disediakan.)

Sebenarnya, bahkan poin-poin itu tidak sepenuhnya akurat, meskipun saya tampaknya hanya menunjukkan setiap hal yang saya katakan. Masalahnya adalah, bahwa daftar poin-poin tidak cukup tepat untuk sepenuhnya akurat. (Saya meninggalkan hal-hal yang tidak tepat sehingga poin-poin tersebut dapat dibandingkan dengan relatif mudah, dan diperiksa dengan relatif mudah.)

Namun, agar lebih akurat, poin pertama harus menunjukkan bahwa shell baris perintah memberikan prioritas:

  • ke sistem file (bukan perintah salin internal ) ketika menentukan backslash, dan kemudian sisa path lengkap, tepat setelah nama perintah internal

Berikut ini akan menunjukkan mengapa saya membuat perbedaan itu:

C: \ di tempat lain> echo elevasi UAC diperlukan untuk baris ini >> \ needext
C: \ di tempat lain> echo elevasi UAC diperlukan untuk baris ini >> \ needext.bat
C: \ di tempat lain> md. \ Copy
C: \ di tempat lain> echo @ Echo subdir >> salin \ needext.bat
C: \ di tempat lain> . \ Copy \ needext
subdir

C: \ di tempat lain> salin \ needext.bat
subdir

C: \ di tempat lain> salin \
        file needext 1 disalin.

C: \ di tempat lain> :: UAC juga diperlukan untuk baris berikutnya
C: \ di tempat lain> del \ needext
C: \ di tempat lain> del \ needext.bat

(Perhatikan bahwa perintah salin terakhir mencari file yang disebut \ needext , karena perintah salin internal digunakan. File \ needext.bat hanya dibuat untuk membantu dengan mudah menunjukkan bahwa itu tidak pernah digunakan oleh baris perintah yang termasuk kata salin .)

Pada titik ini, saya menetapkan beberapa inkonsistensi (dengan perilaku perintah salin ) ketika backslash digunakan ...

Selanjutnya saya akan menunjukkan bahwa ada beberapa konsistensi antara perintah-perintah ini. (Jadi, ada konsistensi ... um ... kadang-kadang. Kita mungkin hanya memiliki konsistensi, tidak konsisten.) Apa yang akan saya tunjukkan selanjutnya adalah bahwa perintah cd berperilaku seperti perintah salin ketika suatu periode digunakan. The copy perintah menggunakan perintah internal, dan begitu juga dengan cd perintah.

C: \ sesuatu> md \ yetmore.

C: \ sesuatu> cd \ yetmore.

C: \ sesuatu \ yetmore> md \ md.
C: \ sesuatu \ yetmore> gema gema subdir >> md \ test.bat
C: \ sesuatu \ yetmore> . \ md. \ test
subdir

C: \ something \ yetmore> md. \ test

C: \ something \ yetmore> md. \ test
subdirektori atau file. \ test sudah ada.

C: \ something \ yetmore> :: Kesalahan itu menunjukkan kami menjalankan perintah internal.
C: \ something \ yetmore> md .. \ test
C: \ something \ yetmore> md. \ Cd
C: \ something \ yetmore> salin. \ Md cd
. \ Md \ test.bat
        1 file disalin.

C: \ something \ yetmore> . \ Cd. \ Test
subdir

C: \ something \ yetmore> cd. \ Test
C: \ something \ yetmore \ test> :: perintah internal bekerja dengan satu periode
C: \ something \ yetmore \ test> cd ..
C: \ something \ yetmore> . \ cd .. \ test
subdir

C: \ something \ yetmore> cd .. \ test
C: \ something \ test> :: perintah internal juga diprioritaskan ketika dua periode bekas

Jadi, selama sesi tes awal yang sebagian besar berfokus pada perintah cd dan salin (dengan beberapa penggunaan tambahan md dan sedikit del ), satu-satunya saat kita benar-benar mengutamakan filesystem adalah dengan perintah salin , dan kemudian filesystem hanya mengambil prioritas saat menggunakan path lengkap.

Setelah ulasan selanjutnya, saya menemukan bahwa perintah cd juga memberikan prioritas filesystem ketika menggunakan ekstensi. Setidaknya ini berarti perintah-perintah internal diperlakukan sedikit lebih konsisten satu sama lain. Namun, itu juga berarti bahwa kita mendapatkan perilaku yang berbeda berdasarkan nama objek sistem file (file atau direktori). Sepertinya perilaku tersebut menggunakan logika internal yang benar-benar tidak jelas. Oleh karena itu, mengandalkan perilaku ini untuk bekerja di berbagai sistem operasi adalah sesuatu yang mungkin saya anggap tidak aman untuk dilakukan.


"Perilaku yang Anda gambarkan konsisten untuk semua perintah internal untuk penerjemah baris perintah." ipconfigmisalnya berfungsi juga.
Jonas Köritz

@ JonasKöritz: Tidak Anda dapat menempatkan (forward) memangkas tepat setelah perintah " ipconfig " dan yang akan bekerja, misalnya IPCONFIG/ALL. Namun, bukan itu yang saya bicarakan. " Perilaku yang Anda gambarkan " (dalam pertanyaan Anda) adalah perilaku menempatkan periode tepat setelah nama perintah. Jika saya mengetik IPConfig.maka saya mendapatkan kesalahan tentang perintah yang tidak ditemukan. Demikian pula (walaupun ini tidak terkait dengan perilaku yang Anda gambarkan), jika saya mengetik IPCONFIG\ALLmaka saya dapat menjalankan .\IPCONFIG\ALL.BATfile kustom yang saya buat. Jadi /tidak diperlakukan seperti .atau `\`
TOOGAM

1
Saya akan menerima jawaban Anda untuk menghargai pekerjaan dan penelitian yang diperlukan untuk membuatnya!
Jonas Köritz

2
@Calchas Tes sederhana - coba jalankan copy.exeatau copy.comdalam cmd. Itu tidak bekerja - ini tidak dapat dieksekusi.
Luaan

1
@ Luann: Mengenai ipconfig, saya tidak setuju dengan kesimpulan Anda. Pertanyaan ini adalah tentang apa yang diketik di awal baris perintah. Windows / DOS mengidentifikasi executable dengan ekstensi nama file, sehingga Anda tidak dapat menjalankan program yang disebut "ipconfig" tanpa ekstensi (di Windows, tidak seperti Unix yang mengizinkan ini). Mengenai komentar selanjutnya, aku tidak tahu siapa "Calchas" itu. (Ketika Anda menentukan tanda pada, berikut ini biasanya karakter pertama dari pengguna yang muncul di tempat lain di halaman.) Saya setuju, menjalankan " copy.exe" akan menggunakan copyperintah internal (dan lulus .exe). (Anda dapat berlari .\copy.exe)
TOOGAM

41

Anda berasumsi bahwa nama perintah dan argumennya harus dipisahkan oleh spasi, khusus, tetapi ini tidak benar. Selama doa dapat ditafsirkan secara jelas, doa itu sahih.

Dalam hal ini, argumen pertama dimulai dengan .dan .tidak dapat menjadi bagian dari nama perintah, jadi cddan ..hanya diuraikan sebagai dua token yang terpisah.

Biasanya, argumen pertama Anda akan mulai dengan karakter alfabet (misalnya awal jalan), sehingga akan "berdarah" ke nama perintah Anda dan menyebabkan kesalahan ... tapi itu bukan masalah sintaksis. Itu semantik.

Anda dapat melihat efek yang sama di tempat kerja dengan perintah lain, termasuk echo:

echo...
..

Dalam hal ini, kita hanya mendapatkan dua periode karena ini echoperintah itu sendiri memiliki aturan khusus , sehingga berikut:

echo .

atau, dengan ekstensi, ini:

echo.

hanya menghasilkan garis kosong. Itu kenyamanan. Rupanya itu dilaksanakan dengan mengabaikan periode terkemuka dalam argumen.

Hei, ini DOS / Batch. Anda menginginkan kewarasan? : D


2
Saya berasumsi ini karena unik untuk baris perintah windows, bash misalnya tidak akan memungkinkan Anda melakukannyacd..
Jonas Köritz

47
@ JonasKöritz: Itu program yang sama sekali berbeda pada sistem operasi yang sama sekali berbeda. Sepeda saya tidak memungkinkan cd..:)
Lightness Races in Orbit

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

5
@LightnessRacesinOrbit: Awalnya ini adalah jalan pintas penyaringan .dan ..yang muncul sebagai direktori di setiap direktori lain dan sejauh yang saya tahu tidak pernah dimaksudkan untuk menangkap lebih dari itu. Saya benar-benar menganggap model tersembunyi-atribut sebagai atribut file desain yang lebih bersih daripada secara implisit mengikuti dari nama file.
Joey

4
@ joey - Saya pikir poin yang lebih relevan bukanlah bahwa pendekatan DOS lebih sederhana, itu adalah bahwa DOS tidak mengizinkan .dalam nama file , yang berarti itu tidak bisa menjadi bagian dari nama perintah karena itu harus menjadi bagian dari argumen . Bahkan jika DOS telah membagi perintah menjadi argumen seperti yang dilakukan Unix, ia masih akan menempatkan .perintah setelah ke dalam argumen pertama, karena tidak masuk akal untuk memasukkan karakter yang tidak valid ke dalam nama perintah.
Jules

19

The cd..perintah yang benar dan itu didefinisikan seperti itu dalam perintah interpreter asli command.comyang kemudian diberi nama cmd.exe.

Penerjemah perintah tahu bagaimana memproses cd.., karena .merupakan karakter khusus, sama seperti \.


8
Saya kira masalah utamanya adalah bahwa perintah tidak dapat "secara sintaksis salah" karena sintaksinya tidak ditentukan secara formal di mana pun , jadi jika implementasi utama (cmd.exe dan / atau MS-DOS) menerimanya, maka itu harus benar.
grawity

3
Juga, CD bukan program, tetapi perintah internal. Mirip dengan Echo yang juga merupakan perintah internal, ia tidak perlu memiliki ruang untuk itu berfungsi. echo.berfungsi dengan baik, yang akan mencetak baris kosong.
LPChip

2
@Overmind echoe juga tidak akan berfungsi, jadi sama dengan cd, echo, md, dll.
LPChip

2
@ JonasKöritz, .tidak dijatuhkan tetapi hanya spasi ditambahkan. md.testdan md .testkeduanya membuat direktori .test. Mengetik cd.testdan cd .testakan berubah menjadi direktori .test.
daniel.neumann

6
@ JonasKöritz: Karena sintaksinya tidak pernah berupa command-space-argumen.
Lightness Races in Orbit

11

Ini adalah retas kompatibilitas mundur.

Penerjemah baris perintah dirancang agar kompatibel dengan perintah dari penerjemah perintah MSDOS yang asli, yang dirancang agar kompatibel dengan penerjemah perintah CP / M. Baik CP / M maupun MSDOS tidak mengizinkan a .dalam nama file (itu ditafsirkan sebagai pemisah antara dua bagian nama file, nama dasar dan ekstensi). Ini berarti (setidaknya untuk versi awal DOS), juru bahasa perintah dapat mengidentifikasi bahwa jika mencapai '.' (atau memang karakter lain yang ilegal dalam nama file) itu melewati akhir nama perintah dan menjadi argumen perintah. Ini cukup umum digunakan dalam DOS dan CP / M - misalnya, dir/wadalah perintah yang sangat umum, setara dengan dir /warti untuk membuat daftar file dalam format horizontal.

Saat ini, '.' dapat muncul dalam nama file. Ini menyebabkan beberapa komplikasi dalam cara menguraikan perintah, tetapi shell masih mengidentifikasi .yang bukan bagian dari nama file yang tepat sebagai awal dari argumen. Ini diperlukan terutama karena jutaan pengguna telah terbiasa mengetik cd..atau memiliki banyak file batch yang berisi itu atau echo.sejumlah perintah serupa lainnya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.