I'm trying to convert all backslashes () to forward slashes (/) in a variable which contains a file name and location. I've read about this and seen:
%variable:str1=str2%
and
set "var=%var:\=/%"
which I've attempted, but I'm obviously not getting it right.
Here is the relevant section of my .bat script:
FOR %%f IN ("E:\myfiles\app1\data\*.csv") DO (
echo %%f
set "f=%%f:\=/%"
echo %%f
echo.
)
The output show each filename listed twice.
i.e. this line:
set "f=f:\=/%"
is not doing what I want it to. Can anyone see what I am doing wrong?
Within a block statement (a parenthesised series of statements)
, the entire block is parsed and then executed. Any %var%
within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block)
.
Hence, IF (something) else (somethingelse)
will be executed using the values of %variables%
at the time the IF
is encountered.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion
and use !var!
in place of %var%
to access the changed value of var
or 2) to call a subroutine to perform further processing using the changed values.
Note therefore the use of CALL ECHO %%var%%
which displays the changed value of var
.
Your code contains two separate variables called f
.
The first is the loop-control 'metavariable' called f
and referenced by %%f
.
The second is the common environment variable f
which is established by the set "f=..."
statement. This variable can be accessed by using %f%
but within a block
, it will appear to retain the value it had when the controlling for
was parsed (in fact, any %var%
is replaced at parse-time by the value of var
at that time)
metavariables
cannot be used in string-manipulation statements like substrings or substitutes, only common environment variables can be used for these operations, hence you need to assign the value of the metavariable f
to the environment variable f
and then perform the string-substitution task of the environment variable f
.
The twist, of course, is that you must use delayedexpansion
and the !var!
syntax to access the modified value of an environment variable within a block.
So,
setlocal enabledelayedexpansion
for...%%f...do (
echo %%f
set "f=%%f"
set "f=!f:\=/!"
echo !f!
)
echo just for demonstration %f% !f! %%f
This sets the value of f
in the required manner (of course, you could always change the name to avoid confusion...)
The last line is simply to show that the final value acquired by f
can be accessed outside of the loop as either %f%
or !f!
, and that %%f
is out-of-context and shown as %f
.
Another way to do this without delayedexpansion
is
for...%%f...do (
echo %%f
set "f=%%f"
call set "f=%%f:\=/%%"
call echo %%f%%
)
echo just for demonstration %f% !f! %%f
the difference being the use of call
and doubling the %
s, and the final line will show !f!
as just that - a literal, since outside of delayedexpansion
mode, !
is just another character with no special meaning to cmd
.
This will change the back-slashes to forward-slashes in a variable:
set "variable=E:\myfiles\app1\data\*.csv"
set "variable=%variable:\=/%"
echo "%variable%"
This seems to work for me:
echo off
setlocal enabledelayedexpansion
FOR %%f IN ("C:\tools\workspace\*") DO (
set old=%%f
echo !old!
set new=!old:\=/!
echo !new!
echo.
)
Using a seperate variable rather than the loop variable makes the difference, along with enabling delayed expansion as the variable substittion syntex using the loop variable %%f dosn't seem to work.