3

I tried to customize windows command prompt with the following batch file.

@echo off
cls
:cmd
set /p "cmd=%cd%>"
%cmd%
goto cmd

So, when I open the batch file, it just takes my command into cmd variable and executes it and again prompts for a new command.

But the following command echo %cd% outputs only %cd%

Then I enabled delayedexpansion and used echo !cd! and got the desired output.

enter image description here

I think, because of the delayed expansion, cmd variable now holds echo c:\Users\Sourav\Desktop (am I correct?)

But I got confused when I tried to open the command prompt (not the batch file) and tried the following commands.

enter image description here

I thought, I will get c:\Users\Sourav\Desktop but I got !cd!. This contradicts my understanding of how echo !cd! is working in first case.

Why am I getting different output in the second case?

Can anyone suggest any improvement to the batch file, so that I can get desired output just using echo %cd% in first case?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Sourav Ghosh
  • 1,964
  • 4
  • 33
  • 43
  • 1
    The first part I don't understand; `%cd%` should always expand to the current directory unless you're doing some charset trickery. The second part makes sense. CMD only scans the input once for variables to evaluate. When you typed `%cmd%` it expanded to `echo !cd!` and printed that. It didn't scan the line a second time looking for more variables. – Ryan Bemrose Jun 25 '16 at 22:41
  • 1
    The initial result is easy to explain: environment variables are not in general recursively expanded. Delayed expansion is a separate phase, so doing it that way works. As for the last part, some quick experimentation suggests that delayed expansion only works in batch files, not on the command line. Not too surprising. – Harry Johnston Jun 25 '16 at 23:06
  • 2
    as Harry already noted, `setlocal enabledelayedexpansion` only works within batchfiles. By default, delayed expansion on command line is disabled, but you can enable it for a new instance with `cmd /v:on` – Stephan Jun 26 '16 at 05:03
  • Try `prompt=$P$G` instead of your Batch file... – Aacini Jun 27 '16 at 00:22
  • @Aacini I know that. It's just an example with minimum code just to explain the situation. This batch could do other jobs like changing the prompt title with current directory after each command.(like openSUSE customizes the terminal in their distribution) It's not just about changing the prompt. I can add more code to display the time taken by the command to execute etc. – Sourav Ghosh Jun 27 '16 at 09:31

1 Answers1

3

you need another level of parsing. You can use call to do so:

@echo off
cls
:cmd
set /p "cmd=%cd%>>"
call %cmd%
goto cmd
Stephan
  • 53,940
  • 10
  • 58
  • 91
  • I just have another confusion, when does `!cd!` gets expanded? when we set the `cmd` variable? so that `cmd=echo c:\Users\Sourav\Desktop`? or it just stores `cmd=echo !cd!` and when we execute `%cmd%`, then it expands to `c:\Users\Sourav\Desktop`? Does set /p actually expands variables when reading? – Sourav Ghosh Jun 26 '16 at 06:33
  • 3
    it's not `set` which expands variables, it's the parser. It's quite complex, but [here](http://stackoverflow.com/q/4094699/2152082) you can find some good explanations. – Stephan Jun 26 '16 at 06:46