Search code examples
batch-fileexternal

Batch %~f1 works but %~dp1 fails because of spaces


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"

The Error.

Sorry if this is not enough information I know very little Batch.


Solution

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