Perché "cd .." funziona nella riga di comando di Windows?


86

Quando si digita cd..senza uno spazio tra cde ..il prompt dei comandi di Windows passerà felicemente alla cartella principale. C'è una spiegazione per questo comportamento? Il comando non segue il formato standard dicommand<space>arguments

Funziona ma non dovresti?

Inoltre, perché questo non crea risultati coerenti?

eco..


24
La premessa della tua domanda sembra essere rotta. Potete fornire prove per l'affermazione che ciò è sintatticamente errato?
Razze di leggerezza in orbita,

13
Non credo che "command <space> argomenti" sia mai stato il formato standard in cmd (o in uno dei suoi predecessori); si consideri ad esempio dir/ala sintassi VMS simile.
Grawity

6
cd è molto speciale. Puoi digitare cd c:\program filessenza virgolette e funziona ancora
phuclv

20
Ecco un articolo molto divertente che spiega le stranezze della logica della shell di Windows e quale caos può causare: thedailywtf.com/articles/The-Core-Launcher
vsz

3
Perché cd..funziona Perché Microsoft ha avuto il problema di farlo funzionare esplicitamente. cdè un comando incorporato nell'interprete dei comandi di Windows e Microsoft può fare in modo che il proprio interprete faccia quello che vuole. (Come altro esempio, cdanche non è necessario citare intorno alle directory con spazi nel nome.)
jamesdlin

Risposte:


106

Come alcune delle altre risposte / commenti notano, l'idea che ci sia uno spazio dopo il comando non è corretta. Un esempio ben noto è che puoi digitare una barra in avanti dopo un comando, senza prima aver bisogno di uno spazio.

Tuttavia, esiste un altro comportamento che è un po 'meno compreso e consente il " cd.." di cui stai chiedendo. Questo comportamento consente anche che " cd\" funzioni.

Il comportamento descritto è coerente per tutti i comandi interni all'interprete della riga di comando. Se si dispone di determinati simboli, tra cui un punto, una barra o una barra rovesciata, i caratteri precedenti vengono controllati per verificare se si tratta di un comando interno alla shell "interprete della riga di comando" (CMD.EXE o il suo predecessore COMMAND.COM ).

Questo può essere fatto prima di verificare se la parola può fare riferimento a un file o una sottodirectory. Questo è vero per il cdcomando. Tragicamente, quando ho fatto un campione, ho scoperto che ciò non accade con il copycomando, quindi i risultati sono incoerenti: non sono necessariamente gli stessi con tutti i comandi interni. Non ho continuato la mia ricerca per confrontare (molto) anche altri comandi dele dir, quindi suggerisco semplicemente di essere estremamente attento se provi a fare affidamento su ciò che accade senza spazio.

Ora, la domanda è stata posta anche riguardo al comando echo : questa è un'eccezione insolita, in quanto penso echo.sia abbastanza conosciuta dagli esperti di DOS. Questo probabilmente è stato documentato. Il comportamento, almeno nella CMD di Win7 , è che se il comando inizia con " echo.", il primo periodo viene ignorato. Quindi, " echo..hi" si trasforma in output di " .hi". Il motivo è che " echo." può essere utilizzato per stampare una riga vuota. Al contrario, con Unix, puoi farlo semplicemente eseguendo il echocomando " " da solo. Tuttavia, in DOS, l'esecuzione del echocomando " " da solo produrrà l' impostazione " echo " corrente . Allo stesso modo, DOS tratta " Echo *Off*" e "Echo *On*"come valori speciali che cambiano l'attuale impostazione dell'eco. Se in realtà vuoi stampare la parola" Off", allora" Echo.Off"fa il trucco (almeno con le versioni abbastanza recenti dell'interprete della riga di comando CMD di Microsoft .)

Quindi, almeno il echocomando ha una spiegazione semi-ragionevole. Per quanto riguarda i restanti comandi, pensavo che i comandi interni avessero la priorità. Tuttavia, quando ho provato a fare alcuni test, ho scoperto che in realtà è piuttosto incoerente. Lo dimostrerò attraverso alcuni esempi che ho documentato qui.


Ecco alcuni esempi. Ho usato un prompt dei comandi con privilegi elevati, in modo che UAC non si lamentasse del fatto che scrivessi nella directory principale. Ciò è stato fatto con CMD.EXE di Microsoft Windows 7. Sospetto che i comportamenti potrebbero essere diversi con altre versioni, come COMMAND.COM rispetto alle versioni precedenti di MS-DOS, o software rilasciato da altre società (COMMAND.COM di DR-DOS).

(Questa risposta è già abbastanza lunga, quindi non includo i comandi per ripulire tutto il casino che ho fatto sul mio filesystem. C'è un po 'di pulizia, ma non molto.)

Ecco un esempio che dimostra che il comando interno crea la precedenza. (Dimostro anche la capacità piuttosto sconosciuta di usare un doppio punto per essere effettivamente un commento, che funziona bene anche nei file batch. Tecnicamente, nei file batch, viene elaborato come un'etichetta che non può essere raggiunta da GOTO e termina essere più veloce del comando REM.)

C: \ qualcosa> md cd
C: \ qualcosa> echo echo subdir >> cd \ a.bat
C: \ qualcosa> md \ a
C: \ qualcosa> . \ Cd \ a.bat
subdir

C: \ qualcosa> :: Che correva dal sottodir
C: \ qualcosa> cd \ a
C: \ a> :: Che ha cambiato la mia directory attuale, quindi cd ha avuto la precedenza

Aggiornamento: dopo ulteriori sperimentazioni, ho scoperto che il comando cd interno ha la precedenza sul filesystem solo se la directory specificata non include un punto. Pertanto, se si dispone di una directory denominata " a.bat ", è possibile eseguire " **cd\a.bat**" e verrà eseguito il file batch.

Questa esplorazione di comportamenti meno comuni (dal momento che la maggior parte delle directory probabilmente non contiene punti) mi ha portato ad aggiornare le mie scoperte. Si scopre che il comando cd si sta effettivamente comportando in modo più simile al comando di copia di quanto pensassi inizialmente.

Anche se inizialmente pensavo che i comandi cd e copy si comportassero in modo diverso, ora ho capito che ciò è dovuto al modello dei nomi che stavo fornendo. Tuttavia, ho rivisto i miei risultati precedenti e ho stabilito che i miei precedenti test documentati aiutano a mostrare alcune delle differenze tra ciò che accade quando un nome include un punto e un'estensione e quando non lo fa. Quindi, sto ancora includendo i miei risultati precedenti di seguito (per lo più invariati, ma con alcuni aggiornamenti molto minori, quindi quello che dico è accurato).

Ecco un esempio che dimostra che la copia , con un percorso completo, non utilizza la stessa precedenza (favorendo il comando interno) di cd quando non viene utilizzata alcuna estensione:

C: \ qualcosa> echo echo root >> \ try.bat
C: \ qualcosa> md copia
C: \ qualcosa> echo echo sottodirectory >> copia \ try.bat
C: \ qualcosa> . \ Copy \ try.bat viene eseguito da sottodirectory
sottodirectory

C: \ qualcosa> copiare \ try.bat
sottodirectory

C: \ qualcosa> :: Eh? Perché questo non ha avuto la precedenza ed è stato eseguito da root?
C: \ qualcosa> :: Apparentemente, il comando di copia interna non aveva la priorità sul controllo di una sottodirectory e di un nome file completo (anche se il comando cd interno aveva la priorità, quando la directory non aveva estensione)
C: \ qualcosa> ::
C: \ qualcosa>:: Un altro test: posso aggiungere periodi inutili alla fine
C: \ qualcosa> . \ Copia .. \ try.bat
sottodirectory

C: \ qualcosa> :: Va bene, fantastico. Ma questo non controllerà la sottodirectory:
C: \ qualcosa> copia .. \ try.bat
        1 file copiati.

C: \ qualcosa> :: Che eseguiva il comando di copia interno

I miei primi risultati hanno indicato che questi risultati dimostrano che la shell della riga di comando dà la priorità:

  • al filesystem (invece del comando di copia interno ) quando si specifica una barra rovesciata subito dopo il nome del comando interno
  • al comando cd interno (anziché al filesystem) quando si specifica una barra rovesciata subito dopo il nome del comando interno.
  • al comando di copia interna (anziché al filesystem) quando si specifica un punto subito dopo il nome del comando interno.

Ciò dimostra chiaramente che il comportamento non è coerente tra il comando copia (con un nome file completo che include un'estensione) e il comando cd (senza estensione come parte del nome della directory). Quando si utilizza una barra rovesciata, il comando copia (con l'estensione completa del nome file) controllerà prima il filesystem, ma il comando cd non lo farà (se la directory non contiene un'estensione).

(Aggiornamento: all'inizio, ho pensato che l'incoerenza fosse basata su comportamenti diversi tra i programmi. In seguito, ho scoperto che l'incoerenza esisteva, ma era causata maggiormente dai parametri forniti.)

In realtà, anche quei punti elenco non sono del tutto precisi, anche se mi è sembrato di dimostrare ogni singola cosa che ho appena detto. Il problema è che l'elenco dei punti elenco non è abbastanza preciso per essere completamente accurato. (Ho lasciato le cose imprecise in modo che quei punti elenco potessero essere confrontati relativamente facilmente e controllati relativamente facilmente.)

Tuttavia, per essere più precisi, il primo punto deve evidenziare che la shell della riga di comando dà la priorità:

  • il file system (invece del interno copia comando) quando si specifica una barra rovesciata, e quindi il resto del percorso completo, subito dopo il nome del comando interno

Quanto segue dimostrerà perché sto facendo questa distinzione:

C: \ elsewhere> echo elevazione UAC necessaria per questa riga >> \ needext
C: \ elsewhere> echo elevazione UAC necessaria per questa riga >> \ needext.bat
C: \ elsewhere> md. \ Copy
C: \ elsewhere> echo @ Eco subdir >> copia \ needext.bat
C: \ elsewhere> . \ Copy \ needext
subdir

C: \ elsewhere> copia \ needext.bat
subdir

C: \ elsewhere> copia \ needext
        1 file copiati.

C: \ elsewhere> :: UAC necessario anche per le righe successive
C: \ elsewhere> del \ needext
C: \ elsewhere> del \ needext.bat

(Si noti che l'ultimo comando di copia ha cercato il file chiamato \ needext , perché è stato utilizzato il comando di copia interno . Il file \ needext.bat è stato creato solo per aiutare a dimostrare facilmente che non è mai stato utilizzato dalle righe di comando che includevano la parola copia .)

A questo punto, ho riscontrato alcune incoerenze (con il comportamento del comando copia ) quando si usa una barra rovesciata ...

Successivamente dimostrerò che esiste una certa coerenza tra questi comandi. (Quindi, c'è coerenza ... um ... a volte. Potremmo avere coerenza, incoerente.) Quello che mostrerò dopo è che il comando cd si comporta piuttosto come il comando copia quando viene usato un punto. Il comando copy usa il comando interno, così come il comando cd .

C: \ qualcosa> md. \ Tuttavia più

C: \ qualcosa> cd. \ Ancora

C: \ qualcosa \ ancora> md. \ Md
C: \ qualcosa \ ancora> echo echo subdir >> md \ test.bat
C: \ qualcosa \ yetmore> . \ md. \ test
sottodirectory

C: \ qualcosa \ ciononostante> md. \ test

C: \ qualcosa \ ancora> md. \ test
Una sottodirectory o un file. \ test esiste già.

C: \ something \ yetmore> :: Questo errore mostra che abbiamo eseguito il comando interno.
C: \ qualcosa \ ancora> md .. \ test
C: \ qualcosa \ ancora> md. \ Cd
C: \ qualcosa \ ancora> copia. \ Md cd
. \ Md \ test.bat
        1 file copiati.

C: \ qualcosa \ ancora> . \ Cd. \ Test
sottodir

C: \ qualcosa \ ancora> cd. \ Test
C: \ qualcosa \ ancora \ test> :: il comando interno ha funzionato con un periodo
C: \ qualcosa \ ancora test> cd ..
C: \ qualcosa \ ancora> . \ cd .. \ test
sottodir

C: \ qualcosa \ ancora> cd .. \ test
C: \ qualcosa \ test> :: anche il comando interno ha la priorità quando due periodi sono Usato

Quindi, durante la sessione di test iniziale che si concentrava principalmente sui comandi cd e copy (con qualche uso aggiuntivo di md e un po 'di del ), l'unica volta in cui il filesystem aveva la priorità era con il comando copy , e poi il il filesystem stava prendendo la priorità solo quando si utilizzava il percorso completo.

Dopo la successiva revisione, ho scoperto che il comando cd dava anche la priorità al filesystem quando si utilizzava un'estensione. Almeno questo significa che i comandi interni vengono trattati un po 'più coerenti tra loro. Tuttavia, significa anche che otteniamo comportamenti diversi in base ai nomi degli oggetti del filesystem (i file o le directory). Sembra che il comportamento stia usando una logica interna davvero molto oscura. Pertanto, contare su questo comportamento per operare su diversi sistemi operativi è qualcosa che probabilmente considererei non sicuro da fare.


"Il comportamento che descrivi è coerente per tutti i comandi interni all'interprete della riga di comando." ipconfigper esempio funziona anche.
Jonas Köritz,

@ JonasKöritz: No. Puoi inserire una barra (in avanti) subito dopo il comando " IPConfig " e funzionerà, ad es IPCONFIG/ALL. Tuttavia, non è quello di cui stavo parlando. " Il comportamento che descrivi " (nella tua domanda) era il comportamento di inserire un punto subito dopo il nome del comando. Se scrivo, IPConfig.ricevo un errore su un comando non trovato. Allo stesso modo (anche se questo non è correlato al comportamento che stavi descrivendo), se scrivo IPCONFIG\ALLposso eseguire un .\IPCONFIG\ALL.BATfile personalizzato che ho creato. Quindi /non vengono trattati come .o `\`
TOOGAM il

1
Accetterò la tua risposta per apprezzare il lavoro e la ricerca necessari per crearlo!
Jonas Köritz,

2
@Calchas Test semplice: prova a eseguire copy.exeo copy.comin cmd. Non funziona, non è un eseguibile.
Luaan,

1
@Luann: Per quanto riguarda ipconfig, non sono d'accordo con la tua conclusione. Questa domanda riguarda ciò che è stato digitato all'inizio di una riga di comando. Windows / DOS identifica gli eseguibili in base all'estensione del nome file, quindi non è possibile eseguire un programma chiamato "ipconfig" senza un'estensione (in Windows, a differenza di Unix che lo consente). Per quanto riguarda il prossimo commento, non so chi sia "Calchas". (Quando si specifica un segno at, di seguito sono in genere i primi caratteri di un utente che vengono visualizzati altrove nella pagina.) Sono d'accordo, l'esecuzione di " copy.exe" utilizzerà il copycomando interno (e passerà .exe). (Puoi correre .\copy.exe)
TOOGAM

41

Supponi che un nome di comando e i suoi argomenti debbano essere separati da uno spazio, in particolare, ma ciò non è vero. Finché l'invocazione può essere interpretata in modo inequivocabile, l'invocazione è valida.

In questo caso, il primo argomento inizia con .e .non può essere parte del nome del comando, così cde ..sono semplicemente analizzato come due gettoni separati.

Di solito, il tuo primo argomento inizierà con un carattere alfabetico (ad esempio l'inizio di un percorso), quindi "sanguinerà" nel tuo nome di comando e causerà un errore ... ma questo non è un problema di sintassi. È semantico.

Puoi vedere lo stesso effetto al lavoro con altri comandi, tra cui echo:

echo...
..

In questo caso, otteniamo solo due punti perché il echocomando stesso ha una regola speciale , in modo che quanto segue:

echo .

o, per estensione, questo:

echo.

genera solo una riga vuota. È una comodità. Apparentemente è stato implementato ignorando un periodo iniziale nell'argomento.

Ehi, questo è DOS / Batch. Vuoi il buonsenso? : D


2
Ho assunto questo perché è unico nella riga di comando di Windows, bash per esempio non ti permetterà di farlocd..
Jonas Köritz,

47
@ JonasKöritz: è un programma completamente diverso su un sistema operativo completamente diverso. La mia bicicletta non lo permette cd..neanche :)
Lightness Races in Orbit il

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

5
@LightnessRacesinOrbit: Inizialmente si trattava di una scorciatoia per filtrare .e ..che appare come directory in ogni altra directory e, per quanto ne so, non è mai stata pensata per catturarne altro. In realtà considero il modello nascosto come attributo di file un design più pulito rispetto al fatto che lo segua implicitamente dal nome del file.
Joey,

4
@joey - Penso che il punto più rilevante non sia che l'approccio DOS fosse più semplice, è che DOS non lo consentiva .nei nomi dei file , il che significava che non poteva far parte del nome di un comando, quindi deve essere stato parte dell'argomento . Anche se DOS avesse diviso il comando in argomenti come fanno le shell Unix, inserirà comunque un .comando dopo nel primo argomento, perché non avrebbe senso inserire un nome non valido nel nome del comando.
Jules,

19

Il cd..comando è corretto ed è stato definito come quello nell'interprete dei comandi originale command.comche in seguito è stato nominato cmd.exe.

L'interprete dei comandi sa come elaborare cd.., perché .è un carattere speciale, proprio come \.


8
Immagino che il problema principale sia che il comando non può essere "sintatticamente errato" perché la sintassi non è specificata formalmente da nessuna parte , quindi se l'implementazione primaria (cmd.exe e / o MS-DOS) lo accetta, allora deve essere corretta.
Grawity

3
Inoltre, il CD non è un programma, ma un comando interno. Simile a Echo, che è anche un comando interno, non ha bisogno di spazio per funzionare. echo.funziona altrettanto bene, che stamperà una riga vuota.
LPChip,

2
@Overmind echoe non funzionerà neanche, quindi è lo stesso con cd, echo, md, ecc.
LPChip

2
@ JonasKöritz, .non viene eliminato ma viene aggiunto solo uno spazio. md.tested md .testentrambi creano la directory .test. Digitando cd.teste cd .testcambierà nella directory .test.
daniel.neumann,

6
@ JonasKöritz: Perché la sintassi non è mai stata argomenti di spazio-comando.
Corse di leggerezza in orbita,

11

È un hack di compatibilità all'indietro.

L'interprete da riga di comando è progettato per essere retrocompatibile con i comandi dell'interprete di comandi MSDOS originale, progettato per essere retrocompatibile con l'interprete di comandi CP / M. Né CP / M né MSDOS hanno consentito a .in un nome file (è stato interpretato come un separatore tra due parti del nome file, il nome base e l'estensione). Ciò significa che (almeno per le prime versioni di DOS), l'interprete dei comandi potrebbe identificarlo se raggiungesse un '.' (o qualsiasi altro carattere illegale in un nome file) ha superato la fine del nome del comando ed è stato inserito negli argomenti del comando. Questo era abbastanza comunemente usato sia in DOS che in CP / M - per esempio, dir/wera un comando molto comune, equivalente al dir /wsignificato di elencare i file in un formato orizzontale.

Al giorno d'oggi, '.' può apparire nei nomi dei file. Ciò causa alcune complicazioni nel modo in cui analizzare i comandi, ma la shell identifica comunque un .elemento che non fa parte di un nome file esatto come l'inizio degli argomenti. Ciò è necessario in gran parte perché milioni di utenti si sono abituati a digitare cd..o hanno un gran numero di file batch che contengono questo echo.o qualsiasi numero di altri comandi simili.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.