编写一个既可以通过管道传输也可以直接输入的脚本

时间:2014-02-01 21:21:52

标签: windows shell scripting cmd pipe

这是来自here的后续问题,根据最初回答此问题的人的建议发布。

我正在尝试创建一个脚本,两者采用管道输入也直接从命令行输入。我写了两个脚本;第一个称为create,另一个称为edit。我给出了下面的代码。

@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
)

我添加了评论,以澄清哪些是哪个,以及我的意图是什么。现在,正常输入(例如,如果我只是在命令提示符中键入create foo.txt)工作正常,但是当我尝试管道时(例如,create foo.txt | edit)我得到奇怪的行为,即编辑脚本尝试在此示例中打开一个完全不同的文件foo.txt!我错过了什么或做错了什么?

1 个答案:

答案 0 :(得分:1)

在批处理文件中,当执行到达一行时,它会被解析然后执行。在分析时,行内的所有变量读取都将替换为其对应的值。

这适用于行和块,其中块是括号中包含的所有行。在执行块内的任何行之前,对块进行重新编译,解析并将变量读取替换为变量值

您在代码中看到的是变量%file%获取其在块内分配的值,然后,在同一个块内,您尝试读取变量值。但由于所有变量读取都已被替换为进入块之前的值,因此无法获得更改的值。

要处理它,需要延迟扩展。当延迟扩展处于活动状态时,您可以向cmd指示某些变量读取应延迟到执行该行的那一刻。你的代码应该是

@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
)

使用!var! sintax访问需要延迟读取的变量。