变量不在命令中解析

时间:2011-06-22 17:30:10

标签: windows batch-file

我有一个使用变量的Windows cmd批处理文件,但在设置它之后使用该变量的任何地方都失败了。

这是我的批处理脚本:

@echo off

if exist Transactions.csv (
    set datestr=%date:~10,4%%date:~7,2%%date:~4,2%%time:~0,2%%time:~3,2%%time:~6,2%
    rename Transactions.csv Transactions-%datestr%.csv
    curl -s -o curl.log --form upload=@Transactions-%datestr%.csv http://192.168.5.217/test_upload.php
    set datestr=
)

文件被重命名为“Transactions-.csv”,curl命令工作正常,因为它按原样发送文件,但我希望它能正确地重命名文件。

如果我注释掉回线,我就会回来:

if exist Transactions.csv (
    set datestr=20112206112720
    rename Transactions.csv Transactions-.csv
    curl -s -o curl.log --form upload=@Transactions-.csv http://192.168.5.217/test_upload.php
    set datestr=
)

请注意缺少%datestr%的区域。

为什么没有正确解析这些变量的任何想法?

4 个答案:

答案 0 :(得分:3)

当括号中包含一个命令块时,将在执行第一个命令之前解析整个块。这意味着,该块中的所有%var%表达式都会被其当时的值替换。这就是为什么当您运行带有%datestr%注释掉的脚本时,您无法取代@echo off

所以你决定将IF语句的正文移到括号之外是正确的。

另一个解决方案是使用延迟扩展:

@echo off

setlocal EnableDelayedExpansion

if exist Transactions.csv (
    set datestr=!date:~10,4!!date:~7,2!!date:~4,2!!time:~0,2!!time:~3,2!time:~6,2!
    rename Transactions.csv Transactions-!datestr!.csv
    curl -s -o curl.log --form upload=@Transactions-!datestr!.csv http://192.168.5.217/test_upload.php
    set datestr=
)

如您所见,使用setlocal EnableDelayedExpansion命令引入了延迟扩展模式。另请注意语法的更改:!而不是%表示相应变量/表达式的延迟扩展。启用延迟展开后,您仍可以在适当的时候使用%进行即时展开。

答案 1 :(得分:2)

请注意,这种解析日期的方式在很大程度上取决于所使用的语言环境。 %DATE%使用完全(无限)可自定义的短日期格式返回当前日期。一个用户可以将其系统配置为返回Fri040811,另一个用户可以选择08/04/2011 ......对于BAT程序员来说,这是一个完整的噩梦。

这个问题有两个解决方案。

解决方案1,暂时更改区域设置。

reg copy "HKCU\Control Panel\International" "HKCU\Control Panel\International-Temp" /f >nul
reg add "HKCU\Control Panel\International" /v sShortDate /d "yyyy-MM-dd" /f >nul
reg add "HKCU\Control Panel\International" /v sTimeFormat /d "HH:mm:ss" /f >nul

执行%DATE%逻辑,例如

set datestr=%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2%
ren test.txt test-%datestr%.txt 

然后恢复语言环境

reg copy "HKCU\Control Panel\International-Temp" "HKCU\Control Panel\International" /f >nul

解决方案2.使用WMIC。

WMIC Path Win32_LocalTime Get Day,Hour,Minute,Month,Second,Year /Format:table

以方便的方式返回日期,以便用FOR。

直接解析它

答案 2 :(得分:1)

如果我创建一个包含以下内容的批处理文件:

@echo off
set datestr=%date:~10,4%%date:~7,2%%date:~4,2%%time:~0,2%%time:~3,2%%time:~6,2%
echo Transactions.csv Transactions-%datestr%.csv
set datestr=

它显示:

C:\Temp>test
Transactions.csv Transactions-012/133612.csv

这告诉我实际导致失败的是您选择的datestr格式 - 日期值包含正斜杠,在文件名中无效,这导致{{1 }} 失败。 (它必须是你在解析日期输出时使用的值;你有一个一个一个错误。)

您在硬编码测试中没有看到它,因为您已经对格式正确的日期进行了硬编码,而不是您在rename中获得的日期。

答案 3 :(得分:1)

我将您的代码复制到.cmd脚本并运行它并成功重命名该文件。但是,我没有在括号中嵌套,而是使用了一个GoTo块引用,并在双引号内包含了datestr连接。这是我用过的代码......

@echo off
if exist test.txt (
    goto RENFILE
) else (
    goto NOTFOUND
)

:RENFILE
set datestr="%date:~10,4%%date:~7,2%%date:~4,2%%time:~0,2%%time:~3,2%%time:~6,2%"
echo %datestr%
rename test.txt test-%datestr%.txt
goto END

:NOTFOUND
echo file not found!
goto END

:END
pause