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
精彩评论