Batch: % in file name - batch-file

I think this is a simple batch programming question, but after much searching, I can't find the answer.
I'm trying to figure out how to refer to files whose names contain difficult characters.
It seems that double quotes have the effect of treating most enclosed characters literally. For example, for a file named ^^.txt, dir "^^.txt" will find the file, while dir ^^.txt won't.
However, I don't know how to escape %. For example, for a file named %ERRORLEVEL%.txt, none of these find the file:
dir "%ERRORLEVEL%.txt"
dir "%%ERRORLEVEL%%.txt"
dir "^%ERRORLEVEL^%.txt"
Any suggestions would be appreciated.

The escape character for the Windows command prompt is ^. It works without the quotes.
dir ^%errorlevel^%.txt
For your other example ^^.txt, use:
dir ^^^^.txt

Always avoid % and ^ in filenames. Rename % to 'percent' in a global file manager.
They are next to impossible to handle properly in many batch commands.

In a batch script you must double the %, eg.:
#echo off
dir %%errorlevel%%.txt
Btw. you should not use cmd default variable or command names for other things (errorlevel).

Related

Passing quotes within quotes in a BATCH file

I have been looking around for a solution to this one, but so far I have been unsuccessful. I am trying to open two programs using a batch file. The problem is that both of the paths to these files contain spaces, and one of these paths is already enclosed in quotation marks. Because of the the second file (.gh file) does not open. I have already tried putting the second path in quotation marks, and using the \ character to escape the quotation marks, but without any result. Any help is appreciated.
#ECHO OFF
cd C:\Users\\Google Drive\Rhino Werk\MT1458\WIP
"C:\Program Files\Rhino 6\System\Rhino.exe" /nosplash /runscript="-grasshopper editor load document open C:\Users\<username>\Google Drive\Rhino Werk\MT1458\WIP\MT1458_HullGenerator_V2.64_NAKIJKMODEL.gh _enter" "C:\Users\<username>\Google Drive\Rhino Werk\MT1458\WIP\MT1458_HullGenerator_V2.59_001.3dm"
#ECHO OFF
cd /d "C:\Users\\Google Drive\Rhino Werk\MT1458\WIP"
"C:\Program Files\Rhino 6\System\Rhino.exe" /nosplash /runscript="-grasshopper editor load document open \"%userprofile%\Google Drive\Rhino Werk\MT1458\WIP\MT1458_HullGenerator_V2.64_NAKIJKMODEL.gh\" _enter \"%userprofile%\Google Drive\Rhino Werk\MT1458\WIP\MT1458_HullGenerator_V2.59_001.3dm\""
This would be following C++ argv rules of escaping inner double quotes with a backslash. Whether this works or not is unknown as I do not have or use Rhino.

Escape characters of a file path argument for a batch file

I was making a batch file to take dragged-and-dropped folders for program input. Everything was working fine until I passed a folder, which for the sake of this post, called foo&bar.
Checking what %1 contained inside the batch file looked like C:\path\to\foo or C:\path\to\foo\foo. If the file path were in quotes it would work, so the only working code that slightly takes this into effect is :
set arg1=%1
cd %arg1%*
set arg1="%CD%"
Which changes directory to the passed argument using wildcards. However this only works once for if there is another folder with un-escaped characters inside the parent folder, passing the child folder would result in the parent folders' value.
I tried the answer of this post, which suggests to output the argument using a remark and redirection statement during an #echo on sequence. However no progress occurred in rectifying the problem. Any suggestions?
To recap, I am looking for ways to pass folders with un-escaped characters as arguments to a batch file. The implementation should preferably be in a batch file, but answers using VBScript are welcome. However the starting program must be in batch as this is the only program of the 3 that accepts files as arguments.
To test this, create a batch file with following code:
#echo off
set "arg1=%~1"
echo "the passed path was %arg1%"
pause
Then create folders called foobar and foo&bar. Drag them onto the batch file to see their output. foo&bar will only return C:\path\to\foo.
OK, so the problem is that Explorer is passing this as the command line to cmd.exe:
C:\Windows\system32\cmd.exe /c ""C:\path\test.bat" C:\path\foo&bar"
The outermost quotes get stripped, and the command becomes
"C:\working\so46635563\test.bat" C:\path\foo&bar
which cmd.exe interprets similarly to
("C:\working\so46635563\test.bat" C:\path\foo) & bar
i.e., bar is considered to be a separate command, to be run after the batch file.
The best solution would be to drag-and-drop not directly onto the batch file but onto, say, a vbscript or a Powershell script or a plain old executable. That script could then run the batch file, either quoting the argument appropriately or putting the directory path into an environment variable rather than on the command line.
Alternatively, you can retrieve the original command string from %CMDCMDLINE% like this:
setlocal EnableDelayedExpansion
set "dirname=!CMDCMDLINE!"
set "dirname=%dirname:&=?%"
set "dirname=%dirname:" =*%"
set "dirname=%dirname:"=*%"
set "dirname=%dirname: =/%"
for /F "tokens=3 delims=*" %%i in ("%dirname%") do set dirname=%%i
set "dirname=%dirname:/= %"
set "dirname=%dirname:?=&%"
set dirname
pause
exit
Note the exit at the end; that is necessary so that cmd.exe doesn't try to run bar when it reaches the end of the script. Otherwise, if the part of the directory name after the & happens to be a valid command, it could cause trouble.
NB: I'm not sure how robust this script is.
I've tested it with the most obvious combinations, but YMMV. [It might be more sensible to use delayed expansion exclusively, I'm not sure. It doesn't seem to be necessary except in the first set command. Jeb's answer here might be a better choice if you're going this route.]
For the curious, the script works like this:
Load the original command line into dirname [necessary for the reason pointed out by jeb]
Replace all the & characters with ?
Replace all the quote marks with *
If a quote mark is followed by a space, suppress the space.
NB: it is necessary to suppress the space to deal with both the case where the path contains a space (in which case Explorer adds quote marks around it) and the case where it doesn't.
Replace all remaining spaces with /
NB: ? * and / are illegal in file names, so these replacements are safe.
At this point the string looks like this:
C:\Windows\system32\cmd.exe//c/**C:\path\test.bat**C:\path\foo?bar**
So we just need to pull out the third asterisk-delimited element, turn any forward slashes back into spaces and any question marks back into ampersands, and we're done. Phew!

batch file to automate tree command > pdf file

I am new to batch files but was looking to create one that would use the tree command to write a .txt file of the directory in which the batch file is located and then convert that .txt file to a Word file or PDF that the every day user could view.
This was my attempt at the first part of the process;
tree %~dp0 > %~dp0/"Folder Contents.txt" /A /F
but this gave me an "Invalid Path" message in the .txt file
If anyone could point me in the right direction it would be greatly appreciated.
Thanks in advance for your help.
JosefZ has placed the correct command in the comments but I thought I would add a bit of an explanation here:
Think of how you path would look like with your command. It would be like C:\PathTo\Batch\/"FolderContent.txt" which actually is not a valid path.
%~dp0 will end with a \ so the / in the command from the question is syntactically incorrect.
Further the double quotes should be placed around the total path as JosefZ did in his comment. If you do not do that the path will contain these quotes and will be invalid.
JosefZ further added double quotes and a single . around and at the end of %~dp0 after your tree command. The quotes are there to include possible whitespaces into your folder-path and the . to include folders with subfolders as well. You will get an error message if you do not.
Last thing is that he placed the output file at the beginning of the command and got rid of spaces. You can basically place your output file anywhere however. Although you should notice that you should not contain spaces between > and your output-file-path.

Escape an asterisk in DOS

I would like to rename a file in DOS. As a result, a dot and an asterisk should be appended to the file name. For example:
rename text.log text.log.*
However this returns:
text.log..
I have also tried to escape the * as follows:
rename text.log text.log.\*
But no way! Do you guys know how I can rename this file appending an .* to the string text.log by using a cmd shell?
Thanks!
You can't - * is a reserved character and so cannot be used in a filename.
https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words

How do I set an environment variable to a value with spaces in a batch file?

I don't know how to describe exactly what I'm trying to do but here's an example batch file that demonstrates what I can't figure out.:
I've got a batch file. Inside that batch file I'm trying to create a directory:
Set CopyFrom = %~dp0
if Exist "%ProgramFiles(x86)" (
Set TargetDir = %ProgramFiles(x86)%\My Directory Name has spaces
)
md %TargetDir%\NewSubFolder
copy %CopyFrom%\SourceFile.zip %TargetDir%\NewSubFolder
My batch file is failing on line 4 Set TargetDir =... with:
\My was unexpected at this time
I'm assuming this is because I have spaces in my path name. I thought I could just wrap my variable with quotes:
Set TargetDir = "%ProgramFiles(x86)%\My Directory Name has spaces"
But then when I get to the line that creates the directory it fails because %TargetDir% is now wrapped in quotes. md "%TargetDir%"\NewSubFolder
Can this be fixed or should I just write a VBScript to sort things out?
Just put your expression in quotes like this:
C:\>Set "TargetDir=%ProgramFiles%\My Directory Name has spaces"
C:\>echo %TargetDir%
C:\Program Files\My Directory Name has spaces
Note: It will expand the variable within the quotes, and if it too has spaces, it will need to be quoted.
Now you can quote it to perform your operation:
md "%TargetDir%\NewSubFolder"
The problem in question here are not the spaces as others suggested, but rather the closing parenthesis in the environment variable ProgramFiles(x86) This causes the parser to think that the block ends prematurely (shameless self-promotion).
Quotes do help in this case because they make the parser jump over the whole quoted part and rightly assume the following parenthesis to be the actual closing one. but the fix might be much easier than that:
if Exist "%ProgramFiles(x86)%" Set TargetDir=%ProgramFiles(x86)%\My Directory Name has spaces
Why use a parenthesized block at all if all you do it put exactly one command into it?
set itself doesn't need any quotes, except when its arguments contain special characters like <, >, |, & which the shell itself aready handles. It isn't a panacea, though which makes handling user input or file contents correctly a pain at times.
Also, please never ever put spaces around the = in a set command. This will cause an environment variable to be created with its name ending in a space and its contents starting with a space. This was partially corrected in Windows 7 by silently creating both the variable with the space at the end and one without:
> set foo = bar
> set foo
foo=bar
foo = bar
But in previous versions of Windows this didn't happen so just never use spaces around the = unless you know this is what you want :-)

Resources