I have a batch file which moves files from one folder to another. The batch file is generated by another process.
Some of the files I need to move have the string "%20" in them:
move /y "\\myserver\myfolder\file%20name.txt" "\\myserver\otherfolder"
This fails as it tries to find a file with the name:
\\myserver\myfolder\file0name.txt
Is there any way to ignore %
? I'm not able to alter the file generated to escape this, such as by doubling percent signs (%%
), escaping with /
or ^
(caret), etc.
Represents a replaceable parameter. Use a single percent sign ( % ) to carry out the for command at the command prompt. Use double percent signs ( %% ) to carry out the for command within a batch file. Variables are case sensitive, and they must be represented with an alphabetical value such as %a, %b, or %c. ( <set> )
When used in a command line, script, or batch file, %1 is used to represent a variable or matched string. For example, in a Microsoft batch file, %1 can print what is entered after the batch file name.
Two percent signs without anything in between (in a batch file) are treated like a single percent sign in a command (not a batch file): %%f.
If you need to use any of these characters as part of a command-line argument to be given to a program (for example, to have the find command search for the character >), you need to escape the character by placing a caret (^) symbol before it.
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:
%
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 yields My %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 like My %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 of execSync
in Node.js.
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 named USERNAME^
, 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.
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"
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With