Change backslash to forward slash in windows batch file
Magoo's helpful answer shows how to perform dynamic substitutions (via delayed expansion) inside a for
loop's (...)
block.
foxidrive's answer shows the general cmd
syntax for performing literal, global string substitutions in variable values (also briefly shown in the question).
Let me complement these answer with a solution that uses PowerShell's CLI:
Note:
In the simple case at hand, this is overkill, and also performs worse than a pure
cmd
solution.However, the technique can be helpful if you need more sophisticated, regex-based string substitutions, via PowerShell's regex-based
-replace
operator.
@echo off
:: Sample path.
Set inPath=C:\foo\bar
for /f "usebackq delims=" %%i in (
`powershell -noprofile -c "\"%inPath%\" -replace '\\', '/'"`
) do set "outPath=%%i"
echo %outPath%
The above yields:
C:/foo/bar
In-line variant, with the input path directly embedded and direct output of the transformed string:
C:\>powershell -noprofile -c "\"C:\foo\bar\" -replace '\\', '/'"
C:/foo/bar
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.
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
.