batch Only execute for certain extension - batch-file

I don't really have a very deep understanding of what I'm doing here but the thing is I cant make it work for just certain file type
FOR %%2 in (*.mp4,*.avi,*mkv) do set fname=%%~n2
FOR %%1 in (*.srt,*.sub) do (
attrib -r %1
PING 1.1.1.1 -n 1 -w 1000 > NUL
cscript "NewReplace.vbs" %1
ren %1 "%fname%".srt
)
So what it DOES is that this is located into %appdata%\Microsoft\Windows\SendTo and when I Right Click-Send to-MyBatch it searches for a MP4, AVI, MKV in the clicked file directory, copies it's name to my file and appends .srt.
What I WANT IT to do is only accept .srt and .sub files, and when it copies the name to append the original extension not always .srt.

Fundamentally, FOR %%2... and similar are errors.
The metavariable (loop-control variable - you've attempted to use 2) must be alphabets and that alphabetic character is case-sensitive (one of the few placs in batch that exhibits case-sensitivity.)
When referencing the value within a for loop, use %%x (where x is your chosen metavariable.)
%n where n is 1..9 means the parameter n provided to the routine, hence %1 means 'the first parameter given to this routine,' so thisroutine something somethingelse would see something as parameter 1 and somethingelse as parameter 2, referenced by %1 and %2 respectively.
Your first line, when corrected, will assign the name part of each filename found in turn from the selected masks (*.mp4,*.avi,*mkv) and the name part of the very last such name found will be assigned to the variable fname.
Similarly, your second for loop will look for all .srt and .sub files, remove any read-only attribute, wait, run your cscript with the entire name (name+extension) of the *.srt or *.sub found, then attempt to rename that file to the name found in the first loop.srt - because that is what you've specified.
The upshot of all this is that the first loop will locate zzz.mkv (if that is the last filename found in the first loop) and assign zzz to fname.
The second loop will rename the first .srt or .sub file found to zzz.srt and since that filename now exists, will fail to rename all of the remaining .srt and .sub files - including zzz.srt.
That's what your code, when the metavariables are fixed, should try to do. It probably isn't what you want it to do, but you've not provided an example, and you've not clearly explained what to do if there are multiple (*.mp4,*.avi,*mkv) files or what your cscript is supposed to do when provided with a filename, or what you want to do about srt and sub files

Related

How to pass a string to a Windows command that expects a file argument? [duplicate]

This question already exists:
How to pass a string to a Windows cmd that expects a file argument? [closed]
Closed 2 years ago.
Suppose a program cook takes one argument: the pathname of a text file containing the recipe of the food to cook. Suppose I wish to call this program from within a batch script, also suppose I already have the recipe in a string variable:
set the_recipe = "wash cucumbers" "wash knife" "slice cucumbers"
cook ... # What should I do here? It expects a file, but I only have a string.
Adapted from here.
How can I pass the recipe to the command when it expects a filename argument?
I thought about creating a temporary file just for the purpose passing a file, but I wish to know if there are alternative ways to solve this problem.
Unfortunately, Batch does not provide a mechanism similar to the Bourne shell heredoc. There are two ways to do this:
Option 1: Change the command
If you have access to the cook executable, you can add a flag to indicate passing a string or list of strings instead of a file. For example, COOK/A might take argument input, while COOK/F takes a file.
Option 2: Use a temporary file
Use a temporary file. The typical way to generate a temporary file is:
SET TEMPFILE=%TMP%\%~N0-%RANDOM%.tmp
ECHO.FILE CONTENT LINE 1 >> %TEMPFILE%
ECHO.FILE CONTENT LINE 2 >> %TEMPFILE%
REM AS MANY LINES AS ARE NEEDED
REM USE THE FILE
DEL/F "%TEMPFILE%" & REM DELETE THE TEMPORARY FILE
Remember that putting "" in an ECHO statement will cause the quotation marks to be included in the file, and that ECHO. must be used to include an indent in the file.
If you mean to convert the variable in your example into a tempfile with each quoted segment on a separate line, you'll need to use FOR:
FOR %A IN (%THE_RECIPE%) DO (
ECHO.%~A >> %TEMPFILE%
)
Including the ~ in the variable substitution strips out the quotation marks that would otherwise end up in the file. If you want the quotation marks in the file, you can omit the tilde.

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!

Accessing unknown number of commands (parameters) in batch file

this one's a bit difficult to explain, but I'll do my best.
I'm passing a list of directories into a batch file via a string array, which is created in Java and then passed into the .bat using Runtime.getRuntime().exec(commands). The trouble I am having is in regards to accessing the commands array, the size of which may vary from execution to execution. For example, during one run, "Commands" may contain the following:
{"cmd.exe", "/C", "Start", "program.bat", "stringA", "stringB", "stringC"}
The first four elements are used to call the batch file, so only strings A, B, and C are passed into the batch file (program.bat) as parameters. However, on the next run, "commands" may look like this:
{"cmd.exe", "/C", "Start", "program.bat", "stringA", "stringB", "stringC", stringD, stringE}
As you can see, there are two more strings added to the parameters list. My question is this: In my batch file I have this:
::Get stringA (param 1)
set stringA=%1
::Get stringB (param 2)
set stringB=%2
::Get stringC (param 3)
set stringC=%3
This takes the three string parameters (from the first "commands" array) and sets local variables to whatever values are passed in to the corresponding parameters. I am wondering if there is a way to determine the number of parameters (from the second "commands" array, for example) from within the batch file, and set/create the proper number of local variables accordingly. I focus primarily on Java, so batch files are still fairly new to me. Any suggestions will be very much appreciated, as I've been trying to figure this one out for a while on my own with no success.
#echo off
setlocal enabledelayedexpansion
set argCount=0
for %%x in (%*) do (
set /A argCount+=1
set "argVec[!argCount!]=%%~x"
)
echo Number of processed arguments: %argCount%
for /L %%i in (1,1,%argCount%) do echo %%i- "!argVec[%%i]!"
For example:
C:> test One "This is | the & second one" Third
Number of processed arguments: 3
1- "One"
2- "This is | the & second one"
3- "Third"
Batch-Script - Iterate through arguments
As stated here:
https://stackoverflow.com/a/14298769/955143
You can read by %1 to %9, and use SHIFT to delete the first element from the array, an then renummerate they to new numbers.
For instance, the %2 becomes %1, and the 10th element becomes the 9th, and you can acess it by %9.
Since the read value become a empty string you have reached the end of the array
You can write a loop (with goto or for) to reade the %1 value, and use SHIFT to rotate the 2nd element to the first position, and check if it isn't empty, them repeat the process.

Storing multi-word strings to a file

I've recently been trying to make a program to simply store text to a file for later viewing, storing it as a .rar file for security against those who don't understand how to extract the text from the .rar (i.e. the less "techy" people)...
I have, however, encountered an error in the program that results in the <word> not expected at this time followed by the .exe closing when I input add/<word> <word>... (i.e. any multi-word string with spaces in between the words [add/<word>, however, does function properly]).
Is there a special rule that must be followed for storing multi-word strings to a .rar or a file in general (I do, however, know that there is a rule for creating/renaming folders/directories)?
The Program Segment:
:command
cls
set /p journal=<journal.rar
echo %journal%
echo.
set /p command=What would you like to do?
cls
if %command%==exit exit
if %command%==help goto help
if %command%==delete echo START; > journal.rar
if %command:~0,4%==add/ echo "%journal%""%command:~4%;" > journal.rar
if %command:~0,5%==edit/ echo %journal:%command:~5%=%;" > journal.rar
goto command
Excuse me. Your question is not clear. There are several confusing points in it, like "followed by the .exe closing" (which .exe is closing?), and the fact that your question is NOT related to .rar files in any way, nor to "storing multi-word strings". However, I can see the following points in it:
When a variable value is expanded with percent signs this way: %command% you must be aware that the variable is first expanded and then the resulting line is parsed. This mean that the value of the variable may introduce errors in the line. For example, in this line: if %command%==exit exit, if the value of command variable is add/one two three, then the line that is parsed is this: if add/one two three==exit exit that, of course, issue an error! (type if /? for further details).
The way to avoid this problem is enclosing both the variable and the comparison value in quotes; this way, if the value have several words with spaces, the whole value is grouped in the IF command for comparison purposes: if "%command%" == "exit" exit. This must be done in every IF command that use the value of the variable.
In the following line:
if %command:~0,5%==edit/ echo %journal:%command:~5%=%;" > journal.rar
you must be aware that the line is parsed from left to right; this means that you can not nest a %variable% expansion inside another one. The way to solve this problem is first complete a %normal% variable expansion, and then a !delayed! variable expansion that will take the previous expanded value. To do that, insert this line at beginning of your program:
setlocal EnableDelayedExpansion
and change previous line by this one:
if "%command:~0,5%" == "edit/" echo !journal:%command:~5%=!;" > journal.rar
For further details, type set /? and carefully read the sections about "delayed expansion".
Here is a sample that can accept multiple words:
set "command="
set /p "command=What would you like to do? "
cls
if /i "%command%"=="have lunch" goto :food

Can't pass file path to a Batch file

I'm new to programming so apologies in advance if this is really simple.
I'm using PA File Sight to monitor a folder for open files. When a file is opened it starts a program (batch file in this case) and passes the entire file path to the variable: $Item(1)$
The batch file looks like this at the moment:
set FILE_PATH="$Item(1)$"
echo.>%FILE_PATH%_IS_OPEN
I'm trying to get the batch file to create a new file with IS_OPEN on the end of it so that users know that a file "is open"
Running the batch file creates the following in it's folder:
$Item(1)$_IS_OPEN
So it's not storing the path for some reason.
I'd suggest you try
set FILE_PATH="%~1"
echo. "%FILE_PATH%_IS_OPEN"
echo.>"%FILE_PATH%_IS_OPEN"
PAUSE
This should set FILE_PATH to the first parameter that the batch file sees - the ~ removes any enclosing quotes
The next line echoes the result to the console and may be removed if the test proves successful.
The third line encloses the proposed filename in quotes to allow the use of spaces in the filename generated.
The PAUSE holds the CMD window open until you press ENTER to allow you to see the results. It too can be removed if your results are as expected.
modified to replace the first 2 characters of the NAME portion with "AA"
set FILE_PATH="%~1"
FOR /f "delims=" %%i IN ("%file_path%") DO (SET dpi=%%~dpi&SET ni=%%~ni&SET xi=%%~xi)
SET file_path=%dpi%AA%ni:~2%%xi%
echo. "%FILE_PATH%_IS_OPEN"
echo.>"%FILE_PATH%_IS_OPEN"
PAUSE
This assumes that it's the first 2 characters that need to be replaced. It works by assuming that the literal-string in the variable file_path is a filename whic, miracle of miracles, it is. dpi is then set to the drive and path, ni to the name and xi to the extension. then the full name is reconstructed, substituting AA for the first 2 characters of the name (dpi (the path) + AA + ni:2 (the name from the second character to the end) + xi (the extension))
$Item(1)$ seems like a constant string. If $Item(1)$ is the name of an actual environment variable, your first line should be
set FILE_PATH="%$Item(1)$%"
Although that seems quite an odd name for a variable.

Resources