Ignore percent sign in batch file
You need to use %%
in this case. Normally using a ^
(caret) would work, but for %
signs you need to double up.
In the case of %%1
or %%i
or echo.%%~dp1
, because %
indicates input either from a command or from a variable (when surrounded with %
; %variable%
)
To achieve what you need:
move /y "\\myserver\myfolder\file%%20name.txt" "\\myserver\otherfolder"
I hope this helps!
The question's title is very generic, which inevitably draws many readers looking for a generic solution.
By contrast, the OP's problem is exotic: needing to deal with an auto-generated batch file that is ill-formed and cannot be modified: %
signs are not properly escaped in it.
The accepted answer provides a clever solution to the specific - and exotic - problem, but is bound to create confusion with respect to the generic question.
If we focus on the generic question:
How do you use %
as a literal character in a batch file / on the command line?
-
Inside a batch file, always escape
%
as%%
, whether in unquoted strings or not; the following yieldsMy %USERNAME% is jdoe
, for instance:echo My %%USERNAME%% is %USERNAME% echo "My %%USERNAME%% is %USERNAME%"
-
On the command line (interactively) - as well as when using the shell-invoking functions of scripting languages - the behavior fundamentally differs from that inside batch files: technically,
%
cannot be escaped there and there is no single workaround that works in all situations:-
In unquoted strings, you can use the "
^
name-disrupter" trick: for simplicity, place a^
before every%
char, but note that you're not technically escaping%
that way (see below for more); e.g., the following again yields something likeMy %USERNAME% is jdoe
:echo My ^%USERNAME^% is %USERNAME%
-
In double-quoted strings, you cannot escape
%
at all, but there are workarounds:-
You can use unquoted strings as above, which then requires you to additionally
^
-escape all other shell metacharacters, which is cumbersome; these metacharacters are:<space> & | < > "
-
Alternatively, unless you're invoking a batch file, , you can individually double-quote
%
chars as part of a compound argument (most external programs and scripting engines parse a compound argument such as"%"USERNAME"%"
as verbatim string%USERNAME%
):some_exe My "%"USERNAME"%" is %USERNAME%
-
-
From scripting languages, if you know you're calling a binary executable, you may be able to avoid the whole problem by forgoing the shell-invoking functions in favor of the "shell-free" variants, such as using
execFileSync
instead ofexecSync
in Node.js.
-
Optional background information re command-line (interactive) use:
Tip of the hat to jeb for his help with this section.
On the command line (interactively), %
can technically not be escaped at all; while ^
is generally cmd.exe
's escape character, it does not apply to %
.
As stated, there is no solution for double-quoted strings, but there are workarounds for unquoted strings:
The reason that "^
name-disrupter" trick (something like ^%USERNAME^%
) works is:
-
It "disrupts" the variable name; that is, in the example above
cmd.exe
looks for a variable namedUSERNAME^
, which (hopefully) doesn't exist. -
On the command line - unlike in batch files - references to undefined variables are retained as-is.
Technically, a single ^
inside the variable name - anywhere inside it, as long as it's not next to another ^
- is sufficient, so that %USERNAME^%
, for instance, would be sufficient, but I suggest adopting the convention of methodically placing ^
before each and every %
for simplicity, because it also works for cases such as up 20^%
, where the disruption isn't even necessary, but is benign, so you can apply it methodically, without having to think about the specifics of the input string.
A ^
before an opening %
, while not necessary, is benign, because ^
escapes the very next character, whether that character needs escaping - or, in this case, can be escaped - or not. The net effect is that such ^
instances are ultimately removed from unquoted strings.
Largely hypothetical caveat: ^
is actually a legal character in variable names (see jeb's example in the comments); if your variable name ends with ^
, simply place the "disruptive" ^
somewhere else in the variable name, as long as it's not directly next to another ^
(as that would cause a ^
to appear in the resulting string).
That said, in the (very unlikely) event that your variable has a name such as ^b^
, you're out of luck.
In batch files, the percent sign may be "escaped" by using a double percent sign ( %% ). That way, a single percent sign will be used within the command line. from http://www.robvanderwoude.com/escapechars.php
I think I've got a partial solution working. If you're only looking to transfer files that have the "%20" string in their name and not looking for a broader solution, you can make a second batch file call the first with %%2 as the second parameter. This way, when your program tries to fetch the second parameter when it hits the %2 in the text name, it will replace the %2 with an escaped %2, leaving the file name unchanged.
Hope this works!
How to "escape" inside a batch file withoput modify the file** The original question is about a generated file, that can't be modified, but contains lines like:
move /y "\\myserver\myfolder\file%20name.txt" "\\myserver\otherfolder"
That can be partly solved by calling the script with proper arguments (%1
, %2
, ...)
@echo off
set "per=%%"
call generated_file.bat %%per%%1 %%per%%2 %%per%%3 %%per%%4
This simply sets the arguments to:
arg1="%1"
arg2="%2"
...
How to add a literal percent sign on the command line
mklement0 describes the problem, that escaping the percent sign on the command line is tricky, and inside quotes it seems to be impossible.
But as always it can be solved with a little trick.
for %Q in ("%") do echo "file%~Q20name.txt"
%Q
contains "%"
and %~Q
expands to only %
, independent of quotes.
Or to avoid the %~
use
for /F %Q in ("%") do echo "file%Q20name.txt"