Reputation: 3140
This is a follow-on question from here, posted at the suggestion of the person who originally answered it.
I'm trying to create a script that will both take piped input and also direct input from the command line. I wrote two scripts; the first is called create
and the other is called edit
. I give the code below.
@echo off
REM create
if -%1-==-- (
REM Piped
set /p name=
copy nul %name% > nul
echo %name%
) else (
REM Not piped
copy nul %1 > nul
)
@echo off
REM edit
if -%1-==-- (
REM Piped
set /p file=
start notepad++.exe %file%
) else (
REM Not piped
start notepad++.exe %1
)
I have added remarks to clarify which is which, and what my intent was. Now, the normal input (for example, if I just type create foo.txt
into the command prompt) works fine, but the moment I try piping (for example, create foo.txt | edit
) I get strange behaviour, namely, the edit script tries to open a completely different file to foo.txt
in this example! What am I missing or doing wrong?
Upvotes: 0
Views: 71
Reputation: 70923
In batch files, when execution reaches a line, it is parsed and then executed. At parse time, all variable reads inside the line are replaced with their corresponding value.
This applies to lines and blocks, where a block are all the lines enclosed in parenthesis. Blocks are readed, parsed, and get variables reads replaced with variables values before executing any line inside the block.
What you are seeing in your code is that the variable %file%
gets its value assigned inside a block, and then, inside the same block, you try to read the variable value. But as all variable reads has been replaced with the value they have before entering the block, you can't get the changed value.
To handle it, delayed expansion is needed. When delayed expansion is active, you can indicate to cmd that some variable reads should be delayed to the moment the line is executed. Your code should be something like
@echo off
setlocal enabledelayedexpansion
REM create
if -%1-==-- (
REM Piped
set /p name=
copy nul !name! > nul
echo !name!
) else (
REM Not piped
copy nul %1 > nul
)
@echo off
setlocal enabledelayedexpansion
REM edit
if -%1-==-- (
REM Piped
set /p file=
start notepad++.exe !file!
) else (
REM Not piped
start notepad++.exe %1
)
variables that need delayed read are accessed using !var!
sintax.
Upvotes: 1