I am trying to create a batch script to send a shortcut of a file to my start menu but I have ran into trouble setting the "Start in" option. I am using Shortcut from Optimum X to do it and this may be an error from their decade old program and not my code.
%~f1 = C:\Program Files (x86)\Example\Example.exe
%~dp1 = C:\Program Files (x86)\Example\
Running
shortcut /f:"%targetfolder%\%fileName%.lnk" /w:"%~f1" /a:c /t:%1
works as intended and creates a shortcut with the "Start in" set to the dir of the file. But running
shortcut /f:"%targetfolder%\%fileName%.lnk" /w:"%~dp1" /a:c /t:%1
fails when it encounters a space, for example if the path is in Program Files the error is
"The Parameter "Files" is invalid
The Syntax of the command is incorrect"
Sorry if this is not enough information I know very little Batch.
Your problem are not the spaces, but how the standard arguments are handled.
In your case, you are not passing the data to a internal command, but to a external executable that will use its own parser (the default C startup code). To this parser a backslash followed by a quote is a escaped quote that does not end the argument.
As your %~dp1 ends with a backslash, it escapes the quote, so the argument continues until the first unquoted space, in your case after Program in the /t switch. So, Files (in the /tswitch) is not recognized as a valid argument.
The usual approach is to remove the ending backslash with something like
for %%a in ("%~dp1.") do (
shortcut /f:"%targetfolder%\%fileName%.lnk" /w:"%%~fa" /a:c /t:"%~1"
)
Here the for command is used to process the path to the file with an added dot. This why when we retrieve the full path to the referenced element (%%~fa) the ending backslash will not be included.
But, if the target folder is the root of the drive, this approach will not work. The ending backslash can not be removed. So, another approach is to avoid the quote scape by simply escaping the backslash
shortcut /f:"%targetfolder%\%fileName%.lnk" /w:"%~dp1\" /a:c /t:"%~f1"
Now the quote is preceded by two backslashes that will be seen as a escaped backslash followed by the closing quote of the argument.
Related
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 have made a shortcut for opening folders based on job numbers for work. It looks through the job directory for the job number and then opens that folder. Unfortunately, this fails when the folder name has a comma "," in it:
IF %JOBNUM%==!JOBTEST! %SystemRoot%\explorer.exe %%G
Where, for example:
%%G = X:\A12300-12399\A123456 - Job with, comma
Instead of opening the job folder, it just opens My Documents (which, I assume, is the default location for Explorer.
Is there a way to let it know that the comma is part of the folder name and not some sort of delimiter?
Try adding the path inside quotes like "path"
Batch files are essentially shell commands executed as a batch. Commands are delimited by space, "," , "=" etc. As shown Here
When you use a pathname with a delimiter, windows takes the first string to be the actual value and discards the rest. Using quotes is explicitly instructing the shell to treat everything inside the quotes as a single unit. That goes the same for %%G.
I am trying to copy a file from one location to another using a .bat file
copy ""\\PRDHILQW01\LVFPF9\MTHHEDGLIAB.TXT" "\\PRDHILFT04\L&i-ia&rs\PRODUCTION\RS-Actuarial\MTL\Download\VTG1\mthhedgliab_%yyyy%%mm%%dd%.txt" /y"
I get this error
The system cannot find the path specified.
'i-ia' is not recognized as an internal or external command,
operable program or batch file.
What do I need to do to get the &s in the file path recognized as legit part of the file path?
Why the extra quotes? The & must be either quoted, or escaped as ^&. Your extra enclosing quotes are making it so that the quoting does not work properly - you have a quoted empty string "" at the beginning, quoted spaces " " between the file names, and " \y" at the end. Everything else is unquoted.
Simply remove the outer quotes and everthing works as you want.
copy "\\PRDHILQW01\LVFPF9\MTHHEDGLIAB.TXT" "\\PRDHILFT04\L&i-ia&rs\PRODUCTION\RS-Actuarial\MTL\Download\VTG1\mthhedgliab_%yyyy%%mm%%dd%.txt" /y
I'm trying to convert this line into Batch how would one start this exe with the arguments!?
Run("""C:\Program Files\Pro Inc\v420\commonfiles\TCL\bin\intel\cron.exe"" ""C:\Program Files\Pro Inc\v420\CommonFiles\Launcher\dank.thc"" -runae")
how does one do this? Thanks!
What seems to be the problem? This should do, I guess (if you are talking about Windows batch files):
"C:\Program Files\Pro Inc\v420\commonfiles\TCL\bin\intel\cron.exe" "C:\Program Files\Pro Inc\v420\CommonFiles\Launcher\dank.thc" -runae
That is, just specify the name of the executable to invoke, including the path if necessary (enclosed in double quotes if the name and/or the path contain spaces and/or other special characters), followed by a list of arguments. An argument may need to be quoted too if there's a chance it would be misinterpreted as several arguments otherwise (or, likewise, if it contains characters with special meaning).
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 :-)