Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignore percent sign in batch file

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.

like image 892
Stagg Avatar asked Dec 15 '09 12:12

Stagg


People also ask

What does %% mean in batch file?

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> )

What does %1 mean in a batch file?

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.

What does %% mean in command line?

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.

How do I escape special characters in CMD?

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.


5 Answers

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!

like image 116
rud3y Avatar answered Oct 19 '22 19:10

rud3y


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 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.


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 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.

like image 30
mklement0 Avatar answered Oct 19 '22 20:10

mklement0


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!

like image 1
dvatreknerd314 Avatar answered Oct 19 '22 20:10

dvatreknerd314


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"
like image 1
jeb Avatar answered Oct 19 '22 20:10

jeb


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

like image 15
greg Avatar answered Oct 19 '22 20:10

greg