开发者

Variables not parsing in commands

I have a windows cmd batch file that uses a variable, but everywhere that variable is used after setting it is failing.

Here is my batch script:

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

The file gets renamed to "Transactions-.csv", and the curl command works OK because it's sending the file as is, but I'd like it to properly rename the file.

If I comment out the echo off line, this is what I get back:

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

Note the missing areas where %datestr% should be.

Any ideas why these开发者_如何学C variables are not properly being parsed?


When you have a block of commands enclosed in parentheses, the entire block is parsed before its first command executes. That means, all the %var% expressions inside that block are replaced with their values at that time. That's why you could see nothing in place of %datestr% when you ran the script with @echo off commented out.

So your decision to move the body of the IF statement outside the brackets was right.

Another solution to that would be to use delayed expansion:

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

As you can see, the delayed expansion mode is introduced with the setlocal EnableDelayedExpansion command. Note also the change of syntax: ! instead of % denote the delayed expansion of the corresponding variable/expression. When delayed expansion is enabled, you can still use % for immediate expansion, where appropriate.


Note that this way of parsing the date depends heavily in the locale used. %DATE% returns the current date using the short date format that is fully (endlessly) customizable. One user may configure its system to return Fri040811 and another user may choose 08/04/2011... it's a complete nightmare for a BAT programmer.

There are two solutions to this problem.

Solution 1, change temporarily the locale.

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

do your %DATE% logic, for example

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 

and then restore the locale back

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

Solution 2. use WMIC.

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

returns the date in a convenient way to directly parse it with a FOR.


If I create a batch file with the following content:

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

It shows:

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

This shows me that what's actually causing the failure is the datestr formatting you've selected - the date value contains a forward slash, which isn't valid in a filename, and this is causing the rename to fail. (It's got to be the values you're using in parsing the date output; you've got an off-by-one error.)

You're not seeing it in your hard-coded test because you've hard-coded the properly formatted date instead of what you're getting in datestr.


I copied your code into a .cmd script and ran it and it successfully renamed the file. However, rather than nesting in parenthesis I did a GoTo block reference and wrapped the datestr concatenation inside of double-quotes. Here's the code I used...

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜