Home > Blockchain >  The Hell of Quotes while using variables with "&"
The Hell of Quotes while using variables with "&"

Time:02-28

I've been sitting here for 3 days now trying to solve the following problem. I need a call function that I can pass a url as a parameter to. However, this URL has an &, which no longer works as soon as I pass the variable as a call parameter. I can't set /& in the Url, because its a dynamic Url.

Every url begins with https:// and ends with &dl=1

@echo off
setlocal enabledelayedexpansion

set "url=!array[2]!"

call :do_download
   
:do_download 
    powershell -c "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; 
       Invoke-WebRequest '%url%' -OutFile 'C:\Program Files (x86)\test.zip'"

But if i try in all versions of quotes, doublequotes, with trimm or other tricks, it dont work :´( I have rly no idea yet. But i need the Url as call-param.

@echo off
setlocal enabledelayedexpansion

set "url=!array[2]!"

call :do_download "%url%"

:do_download 
    powershell -c "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; 
       Invoke-WebRequest '%1' -OutFile 'C:\Program Files (x86)\test.zip'"

If you try it self: you can save a packs.txt with:

Testlink
https://sync.luckycloud.de/d/76ffff3d76ea4e9ab15e/files/?p=/Test.txt&dl=1

The link is to download a .txt file with 200 words from lorem ipsum. and here is the complete code, that will work at this moment, but without call-param. you can set the paths whatever you want, it's only for example. This code runs by itself; the ! are used because later it will be inside an if, but that code is independent of this one.

@echo off
setlocal enabledelayedexpansion

call :readtest
pause
call :do_download
pause

:readtest
    set count=0
    for /f "usebackq tokens=*" %%A in ("C:\Program Files (x86)\Steam\steamapps\common\packs.txt") do (
        set /a count =1
        set url[!count!]=%%A
    )
    set "pack_sd=!url[2]!"
    goto :eof

:do_download 
powershell -c "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest '%pack_sd%' -OutFile 'C:\Program Files (x86)\Steam\steamapps\common\test.txt'"
goto :eof 

If i try the answer with use: :"=

call :do_download "%pack_sd%"
    
:do_download 
    echo TT %1 TT
    set "url=%1"
    set test=%url:"=%
    echo "TT %test% TT"

first echo:

TT "https://sync.luckycloud.de/d/76ffff3d76ea4e9ab15e/files/?p=FTest.txt&dl=1" TT

second echo:

error: command "dl" is wrong or unknown...
"TT "= TT"

If i try the answer with %~1

call :do_download "%pack_sd%"

:do_download 
    echo TT %1 TT
    set url=%~1
    echo "TT %url% TT%

first echo:

TT "https://sync.luckycloud.de/d/76ffff3d76ea4e9ab15e/files/?p=FTest.txt&dl=1" TT

second echo:

error: command "dl" is wrong or unknown...
"TT https://sync.luckycloud.de/d/76ffff3d76ea4e9ab15e/files/?p=FTest.txt TT"

if i use the answer with: '%1:"=' inside powershell command:

call :do_download "%pack_sd%"

:do_download 
        powershell -c "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest '%1:"=' -OutFile 'C:\Program Files (x86)\Steam\steamapps\common\test.txt'"
    goto :eof 

error: "The string has no terminator: '."

CodePudding user response:


Update: Based on the latest edit to your train wreck of a question with ever-changing requirements, %pack_sd:"=% is probably what you're looking for:

:do_download 
  powershell -c "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest '%pack_sd:"=%' -OutFile 'C:\Program Files (x86)\Steam\steamapps\common\test.txt'"
  goto :eof 

It's not clear where !array[2]! comes from, but here's a simplified example that works if the target URL is passed as the first argument (%1) to your batch file:

@echo off
setlocal

call :do_download %1

:: Exit here, so that the code below isn't executed again.
exit /b 

:do_download 
  powershell -c "Write-Output '%~1'"

The above, if invoked with, say, foo.cmd "http://example.org&more" from cmd.exe, would print verbatim http://example.org&more, proving that the value was correctly passed through to PowerShell.

  • %1, if its value contains &, must by definition have been passed in double quotes, otherwise the batch-file call itself would have broken.

  • Because of that, it is safe to pass it on as-is (unquoted) in the call statement.

  • However, in the context of the powershell call, the surrounding double quotes in the %1 value must be removed, so as not to interfere with the "..." surrounding the entire -c argument - that's what %~1 does.


If the %url% value is obtained from a file, as you state, only a slight tweak is necessary: because your %url% value then does not include embedded surrounding double quotes, pass it as "%url%":

@echo off
setlocal

:: Set %array[2]% to a sample value.
set "array[2]=http://example.org&more"

:: Reference it via delayed expansion (why?)...
set "url=!array[2]!"

:: ... and pass it double-quoted.
call :do_download "%url%"

:: Exit here, so that the code below isn't executed again.
exit /b 

:do_download 
  powershell -c "Write-Output '%~1'"

CodePudding user response:

Does this work?

@echo off
setlocal enabledelayedexpansion

set "url=!array[2]!"

call :do_download
   
:do_download 
    powershell -c "$Url=$Env:url; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; 
       Invoke-WebRequest $Url -OutFile 'C:\Program Files (x86)\test.zip'"

  • Related