I have created a small batch file for windows, and I am having a small issue:
I defined a variable which contains a string, the path of a source file:
D:\git_repos\ALM_Sandboxs\Sensor_Config\StateManagement\ssm_state.cpp
I ´d like to extract the path without the file name:
D:\git_repos\ALM_Sandboxs\Sensor_Config\StateManagement\
Since the path can change, and so does the file name, I am having difficulties to do this. There are many ways, but I wasn´t able to use any of them:
The first one would be to count charaters of the file name:
set NumberOfCharacter
and do
set FilePath=%FilePathTemp2:~,%NumberOfCharacter%%
But this doesn´t work. I can only use number with this syntax:
set FilePath=%FilePathTemp2:~,-18% ==> This works, but I´d like to read 18 from a variable
I have read that the batch interpreter can´t resolve the % pairs, so I tried
for /l %%x in (1,1,%strlength%) do set %FilePathTemp2%=%FilePathTemp2:~,-1%
It doesn´t work either, because the for loop seems not able to change FilePathTemp2 with a global scope.
I would be thankfull for any help
for %%a in (D:\git_repos\ALM_Sandboxs\Sensor_Config\StateManagement\ssm_state.cpp) do echo %%~dpa
(this is batch file syntax. To use it directly on command line, replace both %% with a single %)
The usage of modifiers (like %%~dpa) and which modifiers are possible is explained in for /?
Related
I have a file (let's call it version.txt) that contains a version number and some text:
v5.02
Some text explaining
where and how this
number is used
Based on this answer, I use
set /p version=<version.txt
to store the first line of the file in the version variable. Now I'm trying to write a batch script that operates on folders that contain this version number in their name. However, I get unexpected results because something seems to go wrong when I insert the variable in a path. For example, this script
#set /p version=<version.txt
#echo C:\some\folder\%version%\some\file.exe
prints
C:\some\folder\v5.02
instead of
C:\some\folder\v5.02\some\file.exe
What's going on? I have a feeling there are hidden characters of some sort at the end of the text in the variable, because setting the variable by hand to a constant in the script works.
Edit: I'm using Windows 10 with Notepad++ as my editor, if it helps.
I can only replicate your issue, when version.txt uses Unix line endings (LF) instead of Windows (CRLF). for /f is immune to this issue:
for /f "delims=" %%a in (version.txt) do set "verion=%%a" & goto :skip
:skip
echo C:\some\folder\%version%\some\file.exe
goto :skip breaks the loop after reading the first line.
Since everything I tried didn't seem to work, the solution I found in the end is to call the batch script from a Python script. The Python script reads the first line of the version file and passes it as an argument to the batch script. Out of context, it is a bit of an inelegant solution, but in my case the batch script was already called by a Python script, so it's not that terrible.
Here is a minimal example:
version.txt
v5.02
Some text explaining
where and how this
number is used
script.bat
#echo C:\some\folder\release\%1\some\file.exe
script.py
import os
with open("version.txt") as f:
version = f.readline().rstrip()
os.system("cmd /c script.bat %s" % version)
Edit: Following Stephan's comment, I tried to change the line ending in the text file from LF to CRLF and it indeed solves the problem. However, since I don't really have control over everything that writes in that file, the solution above remains the most feasible in my case.
Edit 2: Stephan's answer (with the for loop) is actually a better solution than this one since it avoids having to transfer part of the work to the calling Python script.
What I'd like to do: Add an entry to a Windows 10 context menu for specific file types (e.g. .mp4) that allows me to search for the file name on a website (in my case, IMDB). I got the entry to show up fine, but file names cut off after any space character.
Question: How do I pass the full file name, including spaces, from the windows registry as a parameter to a batch file?
.reg
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\VLC.mp4\shell\Search IMDB\command]
#="\"C:\\test.bat\" \"%1\""
test.bat
SET a="%~n1"
SET z=https://www.imdb.com/search/title/?title=
SET zz=%z%%a%
start "" %zz%
For a file name like movie.mp4 this works. However, file name cool movie.mp4 will in this case open a search page for "cool" which I'm afraid does not help me.
Any help is greatly appreciated!
Replace the spaces with + signs.
According to https://ss64.com/nt/syntax-replace.html that should be something like
SET zzz=%zz: =+%
The batch file should be:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Name=%~n1"
setlocal EnableDelayedExpansion
set "Name=!Name:%%=%%25!"
set "Name=!Name: =%%20!"
start "" "https://www.imdb.com/search/title/?title=!Name!"
endlocal
endlocal
First, read my answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? It explains in detail what is the difference between set variable="value" and set "variable=value". The latter is the recommended syntax.
Second, a URL must be percent-encoded. A normal space character must be encoded with %20 in a URL. The batch file above does that. It percent-encodes first also % in name by %25.
Note: The entire URL is not correct percent-encoded if the string assigned to the environment variable Name contains other characters than and % which need to be percent-encoded for a valid URL too.
Third, the character % must be escaped in a batch file with one more % to be interpreted as literal character even within a double quoted argument string.
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!
I need to create new copies of a single .html file. The file's name is 065.html.
I copied the file into 066.html using the following command:
C:\>copy 065.html 066.html
But I need more. I need to copy up to 090.html
How can I do this? A loop should do this but I don't know the syntax.
I have tried to use the command as shown here,
for /L %%i IN (66,1,90) do copy 065.html 0%%i.html
but I get an error message that says
%%i was unexpected at this time
I have deleted one preceding % signs. It works now.
for /L %i IN (66,1,90) do copy 065.html 0%i.html
Sorry to ask a question which will be an easy one for many of you I guess...
I'm a student in a CG School, but for the need of my project I need to code a simple .bat file to run on many computers. Everything works pretty fine, but now I need to simplify it to gain extra time setting up the .bat.
We have ALWAYS a Path like that :
D:\Project\Production\Shot\Render\Room\maya\scenes\Room_01.mb
I need two variables which store :
project : D:\Project\Production\Shot\Render\Room\maya
scene : Room_01
I think I need a loop which analyzes the path backward and sets the path after seeing 2 \ in order to avoid the file name, and the scenes folder. And I need an other thing to store all the file name ######.mb removing the .mb
I tried many things with substring forum, but it's kinda black magic for me...
So if anyone could help, I would be so grateful to you ! :)
Thank you in advance.
An easy solution is to use a for command. It will allow you to retrieve different properties of a file system reference.
set "fileReference=D:\Project\Production\Shot\Render\Room\maya\scenes\Room_01.mb"
for %%a in ("%fileReference%") do set "scene=%%~na"
Where %%~na is the name of the element being referenced by the for replaceable parameter %%a
for %%a in ("%fileReference%\..\..") do set "project=%%~fa"
Where %%~fa is the full path of the element being referenced by the for replaceable parameter %%a
A for loop is typically needed here. The first for loop grabs the last element of the string when split by a backslash. The path is then modified to have the file name removed from it, and then another for loop grabs the end off that string in the same manner.
#echo off
set my_path=D:\Project\Production\Shot\Render\Room\maya\scenes\Room_01.mb
for %%F in ("%my_path%") do set file=%%~nxF
echo.%file%
call set modded_path=%%my_path:\%file%=%%
for %%F in ("%modded_path%") do set folder=%%~nxF
echo.%folder%