1

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 [email protected] http://192.168.5.217/test_upload.php
    set datestr=
)

Note the missing areas where %datestr% should be.

Any ideas why these variables are not properly being parsed?

1
  • Found my solution after trial and error. Variables only get parsed once while inside conditionals. I moved my SET commands outside the IF statement and it all worked. Commented Jun 22, 2011 at 17:38

4 Answers 4

3

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

1 Comment

While the real issue for my original question was due to the variables only being parsed once inside the brackets, I appreciate you giving me this further information, and will incorporate this into my batch script and hopefully make it work more consistently. Thanks!
1

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.

2 Comments

I tested all my date strings, and on my system (Windows Vista), the output of the variable is valid: ` C:\>echo %datestr% 20112206111637 `
You must be set to a different locale or something than I am. I tested on XP and Win7 with the same results, but mine are both set to US locale. Glad you got it worked out. :)
1

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

1 Comment

The result was that my example renamed "test.txt" to "test-20112206134545.txt" There were no other characters inserted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.