I've encountered a bit of an issue in a Batch script I am making.
In this script, I want to it react to my pressing a button the moment I press it, and 'set'ting a new variable without having to press Enter.
Currently, it's like this;
set b=
set /p b=
ig %b%==a (
goto Success
)
It allows me to press the button I want, however I don't want it to wait until I press Enter afterwards.
For VISTA and later
If you know your script will run on Vista or later (not XP), then you can use the choice command. You must specify which characters to accept. By default, CHOICE is case insensitive. The returned ERRORLEVEL corresponds to the position of the selected letter within the choice list.
For example, to wait for the user to press A, B, or C (case sensitive) and store the key value in a variable:
setlocal enableDelayedExpansion
set "list=ABC"
choice /cs /c "%list%"
set "list=.%list%"
set "key=!list:~%errorlevel%,1!"
echo %key%
Full documentation is available from the command line by typing HELP CHOICE or CHOICE /?
For all modern Windows, including XP
I was introduced to a very clever solution that works on XP and beyond when I was developing my batch implementation of the SNAKE game. This solution allows you to capture nearly any key press.
set "key="
for /F "usebackq delims=" %%A in (`xcopy /w "%~f0" "%~f0" 2^>NUL`) do (
if not defined key set "key=%%A"
)
set "key=%key:~-1%"
set key
use choice in batch
choice /c YN /m "Is Yes"
if ( %ERRORLEVEL% == 1 ) (
ECHO "SUCCESS"
)
Related
What I am trying to do is a backup by cmd commands but the problem is when I am taking the USB backup to another PC to back up the drive names are different.
For example when I do:
XCOPY G:\*.BMP X:\ /h/i/c/k/e/y/r/d
In the other computer the drives will not be G and X.
What I am seeking to do is if it is possible to make a program that I can enter with the keyboard what drive I want to backup and to what drive.
For example:
XCOPY "driver name keyboard input":\*.BMP "driver name keyboard input":/" /h/i/c/k/e/y/r/d
Yes, it can be done using a PowerShell or batch-file script (cmd tag seems to imply Windows OS).
Let's choose the latter. Next batch-file code snippet would do the same as the command in question: XCOPY G:*.BMP X:\ /h/i/c/k/e/y/r/d:
set "DriveIn=G"
set "DriveOu=X"
XCOPY %DriveIn%:*.BMP %DriveOu%:\ /h/i/c/k/e/y/r/d
Instead of hard-coded DriveIn and DriveOu, you can prompt for user input:
set /P "DriveIn=please choose SOURCE drive letter "
set /P "DriveOu=please choose TARGET drive letter "
XCOPY %DriveIn%:*.BMP %DriveOu%:\ /h/i/c/k/e/y/r/d
Hints for (necessary!) validity checks:
:dfromscratch
set "DriveIn="
set "DriveOu="
:dsource
set /P "DriveIn=please choose SOURCE drive letter "
rem basic validity check
if not defined DriveIn goto :dsource
if not exist "%DriveIn%:\" goto :dsource
:dtarget
set /P "DriveOu=please choose TARGET drive letter "
rem basic validity check
if not defined DriveOu goto :dtarget
if not exist "%DriveOu%:\" goto :dtarget
if /I "%DriveIn%"=="%DriveOu%" goto :dfromscratch
rem involve more validity check here!!!
XCOPY %DriveIn%:*.BMP %DriveOu%:\ /h/i/c/k/e/y/r/d
Some hints for (more) validity checks.
To show available disk drives:
wmic logicaldisk get Description, DeviceID, DriveType, FileSystem, VolumeName
To get a list of available disk drives, use for /F loop (note %%G in a batch script):
for /F %%G in ('
wmic logicaldisk where "DriveType != 5" get DeviceID^, DriveType^|find ":"
') do echo %%G
or next oneliner (note %G in cmd): copy&paste into an open cmd window:
for /F %G in ('wmic logicaldisk where "DriveType != 5" get DeviceID^, DriveType^|find ":"') do #echo %G
Another approach (only a draft, needs more elaboration): build a list of available drive letters %drives% and use choice command instead of set /P:
set "drives=GX"
choice /C %drives% /M "Select SOURCE drive letter"
OK, here goes...
I'm building a batch file with a menu that is set dynamically according to settings in multiple ini files, I used a script suggested to me in a previous question here.
Now, I need to add user input that export the selected menu option to another variable, in normal menu, that is not set dynamically it's easy enough, I've done it many times but I can't figure out how to do so in this instance.
Here's my current script:
#echo off
setlocal EnableDelayedExpansion
:LangMenu
for /L %%D in (1,1,20) do (
if exist Common\Settings\Data%%D.ini for /F "eol=# tokens=1,2 delims==" %%a in (Common\Settings\Data%%D.ini) do (
set line=%%a
if "!line:~2,5!" neq "clude" (
REM Define "normal" variables, i.e. Compressor, Method, etc.
set %%a=%%b
) else if "!line:~7!" neq "" (
REM Define the base array elements, i.e. D1IncludeAR=%%b, D1ExcludeAR=%%b, ...
set D%%D%%a=%%b
REM Set Show?? array elements with value equal 1, i.e. ShowAR=1, ...
REM when anyone of DiInclude?? or DiExclude?? corresponding elements was given
if defined D%%D%%a set Show!line:~7!=1
)
)
)
:LangContinue
REM Define a list of language abbreviations, i.e. "langs=AR CZ DE ..."
REM and the corresponding language names array, i.e. lang[AR]=Arabic, ...
REM At same time, calculate original OptNum
for %%a in ("AR=Arabic" "CZ=Czech" "DE=German" "EN=English" "ES=Spanish" "ESMX=Spanish (Mexico)"
"FR=French" "HU=Hungarian" "IT=Italian" "JP=Japanese" "KR=Korean" "PL=Polish"
"PR=Portuguese" "PRBR=Portuguese (Brazil)" "RU=Russian" "ZH=Chinese") do (
for /F "tokens=1,2 delims==" %%b in (%%a) do (
set "langs=!langs! %%b"
set "lang[%%b]=%%c"
set /A "OptNum+=Show%%b"
)
)
:LangSelect
cls
REM Show the language menu
set #=0
for %%a in (%langs%) do (
if defined Show%%a (
set /a #+=1
echo [!#!] !lang[%%a]!
)
)
set /p SelectLang=Please Choose The Language You Want:
if not "%SelectLang%"=="" Goto LangSet
if "%SelectLang%"=="" goto LangError
:LangError
cls
Echo ERROR: No Language Selected!!
pause
goto LangSelect
:LangSet
if "%SelectLang%"=="1" set LangIs=1
echo Selected Language = %LangIs%
Please note: I just put 1 in the set LangIs for the time being so I won't get echo is off message, it's not at all what I need, just a placeholder.
What I need is to set LangIs variable to the picked option...
An example:
Menu output is this:
[1] Arabic
[2] German
[3] English
[4] Spanish
[5] Italian
Please choose the language you want:
The variable language in the above example can be any languages, even up to 16 languages can be listed, the numbers are set dynamically so if available languages where different 5 languages it was still 1-5.
I need a way that the numbered choice entered by the user will write a variable with the Language name shown by it, so, for example, if the user type 5, I need a variable, that will have either "Arabic" or "AR" in it.
so, for example, if I use the echo command to show the choice it should output something like this if the number 1 is selected (in above menu example):
Selected Language = AR
or
Selected Language = Arabic
Or whatever language is assigned to the number 1 in the menu.
This variable, will have to be checked later on in my script up to 20 different times to check what language is selected in order to set another variable according to the selected language.
Any suggestions will be much appreciated.
:LangSelect
cls
REM Show the language menu
set #=0
for %%a in (%langs%) do (
if defined Show%%a (
set /A #+=1
echo [!#!] !lang[%%a]!
set "option[!#!]=%%a"
)
)
set /P "SelectLang=Please Choose The Language You Want: "
if defined option[%SelectLang%] Goto LangSet
:LangError
cls
Echo ERROR: Invalid Language Selected!!
pause
goto LangSelect
:LangSet
set "LangIs=!option[%SelectLang%]!"
echo Selected Language = %LangIs% (!lang[%LangIs%]!)
Okay, this is kind of complicated so ill try to explain it as best as is can.
I am currently writing a simple program for my own use using notepad.
I am using the language batch and running the program through Command Prompt.
Part of the Program lets you access an account you created with username and password:
set /p USERNAME1= Username?
findstr /n "%USERNAME1%" Usernames.txt
In Usernames.txt are the usernames of each account that has been created, one per line.
If your username is found, it is displayed along with the line number before it in the program.
It then asks for your password:
set /p PASSWORD1= Password?
This is where the problem starts. When the accounts are created, the usernames are stored, one per line, in Usernames.txt , and so are the passwords but in Passwords.txt
I need the program to check if the password you typed is the same as the password on the same line number the username is on, in Passwords.txt
I know this is complicated but if anyone can help it would be greatly appreciated!
Thanks
You're using findstr /N to get the line number of usernames.txt, which is a good start. You're getting the entire line, prefixed with the line number and a colon :.
So for /F can be used to extract the number only. The option string "tokens=1 delims=:" defines to divide the found line at the (first) :, so the line number is separated from the user name.
Finally, another for /F can be used to get the line of the passwords.txt files.
Putting all those things together, the following code snippet emerges:
set /P USERNAME1=Username?
set /P PASSWORD1=Password?
set /A LINENUMBER=0
for /F "tokens=1 delims=:" %%I in (
'findstr /N /I /X /C:"%USERNAME1%" "\path\to\usernames.txt"'
) do (
set LINENUMBER=%%I
goto :CONTINUE1
)
:CONTINUE1
set /A LINENUMBER-=1
if %LINENUMBER% lss 0 (
exit /B
) else if %LINENUMBER% equ 0 (
set SKIPPING=
) else (
set SKIPPING=skip=%LINENUMBER%
)
for /F "usebackq %SKIPPING% delims=" %%I in (
"\path\to\passwords.txt"
) do (
if "%%I" equ "%PASSWORD1%" (
goto :CONTINUE2
)
exit /B
)
:CONTINUE2
rem do something...
So the variable USERNAME1 holds the entered user name to search and PASSWORD1 the entered password.
If the user name cannot be found in usernames.txt, or the entered password does not match the found one, the script is terminated using exit /B.
Note that user names are compared in a case-insensitive manner (/I switch), but the password are compared case-sensitively.
Creating a batch script in Windows XP. Here's a snippet of code I'm having problems with:
::==============================================================::
::How many scripts are included in this program?
SET NumOfScripts=4
::==============================================================::
:mainmenu
CLS
ECHO [MAIN MENU]
ECHO Please choose from the following options to run a particular script:
set /p choice="[1] SCRIPT1.bat | [2] SCRIPT2.bat | [3] SCRIPT3.bat | [4] SCRIPT4.bat : "
IF %choice% EQU 1 CALL :SCRIPT1
IF %choice% EQU 2 CALL :SCRIPT2
IF %choice% EQU 3 CALL :SCRIPT3
IF %choice% EQU 4 CALL :SCRIPT4
REM Wrong Choices
IF %choice% GTR %NumOfScripts% (
(ECHO You have entered an invalid option. Please press any key to be taken back to the main menu.) & PAUSE & GOTO:mainmenu
)
IF %choice% LEQ 0 (
(ECHO You have entered an invalid option. Please press any key to be taken back to the main menu.) & PAUSE & GOTO:mainmenu
)
ECHO You have entered an invalid option. Please press any key to be taken back to the main menu
PAUSE & GOTO:mainmenu
Looking under REM Wrong Choice, the first two arguments work as they should, however, if the user enters in no value (just presses the enter key) it automatically terminates the script. I've added IF NOT DEFINED choice and that doesn't work... I also tried IF [%choice%]==[] and IF [%choice%] EQU [] and those don't work either.
Here's the funny thing... you enter an invalid digit, say 5 or -1, it will give the echoes and go back to the main menu as it should... THEN if you just press enter without a value inserted, it will echo and go back to the main menu as it should.
My question is how do you get it to recognize that the user did not enter a value for set /p on the first go?
You can initialize choice to some invalid value before set /p, e.g.:
SET choice=none
To print the appropriate error message, you can do
IF %choice% EQU none (
(ECHO You did not select an option.) & PAUSE & GOTO:mainmenu
)
Set /p doesn't change the content of a variable, if the user doesn't enter text.
So you can simply set your variable to nothing to detect if the user enter anything.
Set "choice="
Or you can use the errorlevel, as it is set to 1 if the input is empty
But be careful, as it doesn't reset it to 0. So you have to force it yourself before.
cd.
Set /p choose=
If %errorlevel%==1 goto empty
And you should use the variables with delayed expansion, as it is always safe.
Else a user can break your script with input like "&exit"
Can anybody help with effective and safe way of removing quotes from batch variables?
I have written a batch file which successfully imports a list of parameters %1, %2, %3 etc. and places them into named variables. Some of these parameters contain multiple words, and therefor are enclosed in double quotes.
> "Susie Jo" (%1)
> "Smith Barnes" (%2)
> "123 E. Main St." (%3)
These %variables are next placed in named variables:
> set FirstName=%1
> set LastName=%2
> set ShipAddr=%3
verification of variables is done by echo.
> echo.%FirstName%
> echo.%LastName%
> echo.%ShipAddr%
results display as
"Susie Jo"
"Smith Barnes"
"123 E. Main St."
I need to eliminate the included quotes on selected variables. For instance, FirstName and LastName are used elsewhere and must not include quotes.
In a test batch file I was successful at eliminating quotes using the ~tilde character in variables.
> set FirstName=%~1
> set LastName=%~2
I thought I had the solution, but I soon experienced unusual behavior with execution of batch files. Suddenly CMD is no recognizing long path statments. Normal execution of batch file from full path
> C:\Documents and Settings\Administrator\My Documents\Txt\batchtest\dataout.bat
returns
> 'C:\Documents' is not recognized as an internal or external command....
So it would appear that the addition of the ~tilde character to the in-coming %1 %2...%n variables has caused some change. Possibly some environment variables have been altered?
I also tried clearing quotes from within variable with various attempts using the FOR command. That seems awkward and I have been unable to learn how to accomplish this by creating a list of variable to perform the task:
something like this:
for %%g in (%FirstName% %LastName%) do (
set %%g=%%~g
set %%h=%%~h
set FirstName=%%~g
set LastName=%%h
echo.%FirstName% %LastName%
)
I think I have two issues.
My 'short and sweet' idea of inserting ~tilde in the incoming %1 %2 variables (%~1, etc) seems to have affected some settings and altered how CMD navigates long pathnames.
I'm still in search of a clean and easy way to eliminate quotes from selected named variables.
Any help for those more experienced would be most appreciated. I'm at the end of my skills here... need some guidance please!
edit 12/26/2009 13:36 PST
entire batch file:
:: dataout.bat
:: revision 12/25/2009 add ~tilde to incoming %variables to eliminate embedded "quotation marks.
:: writes address list using command line parameters
:: writes data output list for QBooks IIF import
:: writes Merchant Order data for RUI
:: sample command line string for testing
:: listmail[firstname][lastname]["address string"]["city string"][state][zip][Order#][PurchDate][Regname]["FirstName LastName"][TransactionID][PaymentMethod][Total][ProductID][Qty][Price_Each][PackPrep] [Shipping] [CommissionPmt] [Invoice#]
:: example: dataout Bellewinkle Moose "123 Green Forest Way" "Vancouver" WA 98664 1004968 05/25/2009 "Bellewinkle Moose" "Olive Oyl" 101738 "On Account" 20.67 FK-1P 1 8.95 3.00 1.39 239
#echo off
cls
c:
cd\
cd documents and settings\administrator\my documents\txt\batchtest
echo processing %1 %2
:VARISET
:: Convert %n command line parameters to string variables
set ($FirstName)=%~1
set ($LastName)=%~2
set ($BillingAddress1)=%~3
set ($BillingCity)=%~4
set ($BillingState)=%~5
set ($BillingPostal)=%~6
set ($OrderNumber)=%~7
set ($Purch_Date)=%~8
set ($RegistrationName)=%~9
shift
set ($TransactionID)=%~9
shift
set ($PaymentMethod)=%~9
shift
set ($Total)=%~9
shift
set ($ProductIdentifier)=%~9
shift
set ($Quantity)=%~9
shift
set ($Price_Each)=%~9
shift
set ($Pack_Prep)=%~9
shift
set ($Shipping)=%~9
shift
set ($ServiceFee)=%~9
shift
set ($Discount)=%~9
shift
set ($Invoice)=%~9
shift
set ($UnitPrice)=%~9
set _ShipCombName=%($FirstName)% %($LastName)%
echo ship combo name is %_ShipCombName%
pause
:: write string varibables to logfile
echo FN %($FirstName)% LN %($LastName)% BA %($BillingAddress1)% %($BillingCity)% %($BillingState)% %($BillingPostal)% %($OrderNumber)% %($Purch_Date)% %($RegistrationName)% %($TransactionID)% %($PaymentMethod)% %($Total)% %($ProductIdentifier)% %($Quantity)% %($Price_Each)% %($Pack_Prep)% %($Shipping)% %($ServiceFee)% %($Discount)% %($Invoice)% %($UnitPrice)% %_ShipCombName% >> d_out_log.txt
:: Assign Account by Service Provider
IF /i %($PaymentMethod)%==Amazon Receivables SET _QBAcct=Amazon.com
:: 12-25-2009 added second Amazon pm't method for versatility
IF /i %($PaymentMethod)%==Amazon SET _QBAcct=Amazon.com
IF /i %($PaymentMethod)%==MAST SET _QBAcct=Auth/Net
IF /i %($PaymentMethod)%==MasterCard SET _QBAcct=Auth/Net
IF /i %($PaymentMethod)%==Visa SET _QBAcct=Auth/Net
IF /i %($PaymentMethod)%==PayPal SET _QBAcct=PayPalPmts
IF /i %($PaymentMethod)%==On Account SET _QBAcct=%($RegistrationName)%
IF /i %($PaymentMethod)%==Mail SET _QBAcct=%($RegistrationName)%
IF /i %($PaymentMethod)%==AMER SET _QBAcct=Auth/Net
IF /i %($PaymentMethod)%==DISC SET _QBAcct=Auth/Net
:: Assign Rep designator based on QBAccount
IF /i %($PaymentMethod)%==Amazon Receivables SET _Rep=Amazon
:: 12-25-2009 added second Amazon pm't method for versatility
IF /i %($PaymentMethod)%==Amazon SET _Rep=Amazon
IF /i %($PaymentMethod)%==MAST SET _Rep=BlueZap
IF /i %($PaymentMethod)%==MasterCard SET _Rep=BlueZap
IF /i %($PaymentMethod)%==Visa SET _Rep=BlueZap
IF /i %($PaymentMethod)%==PayPal SET _Rep=BlueZap
IF /i %($PaymentMethod)%==On Account SET _Rep=R B
IF /i %($PaymentMethod)%==Mail SET _Rep=R B
IF /i %($PaymentMethod)%==AMER SET _Rep=BlueZap
IF /i %($PaymentMethod)%==DISC SET _Rep=BlueZap
:: check for duplicate address data
findstr /i /s "%_ShipCombName%" addrlist.txt
echo errorlevel: %errorlevel%
if errorlevel 1 goto :ADDRWRITE
if errorlevel 0 goto :ADDRFOUND
:ADDRWRITE
echo %_ShipCombName% >> addrlist.txt
echo %($BillingAddress1)% >> addrlist.txt
echo %($BillingCity)% %($BillingState)% %($BillingPostal)% >> addrlist.txt
echo. >> addrlist.txt
echo Address File Written
:ADDRFOUND
echo selected rep is %_Rep%
echo selected account is: %_QBAcct%
pause
:: RUI OUT
:: write Merchant Order ID & RUI Order ID to RUI
:: check for duplicate RUI data in writeRUI.txt
cd..
cd RegKOut
find /i "%($OrderNumber)%" writeRUI.txt
echo errorlevel: %errorlevel%
if errorlevel 1 goto :RUIWRITE
if errorlevel 0 goto :IIFWRITE
:RUIWRITE
echo %($Invoice)% %($OrderNumber)% >> writeRUI.txt
:: end write RUI
:: IIF OUT
:IIFWRITE
:: Check for duplicate invoice data in writeIIF.txt
find /i "%($OrderNumber)%" writeIIF.txt
echo errorlevel: %errorlevel%
if errorlevel 1 goto :HEADWRITE
if errorlevel 0 goto :LINEWRITE
:HEADWRITE
:: write Header, Ship/Handling, discount, Rep & commission data to QB IIF import file
echo %($OrderNumber)% %($Purch_Date)% Invoice %($TransactionID)% %_QBAcct% Accounts Receivable %($Total)% %_Rep% >> writeIIF.txt
echo H/P %($Pack_Prep)% 1 ? >> writeIIF.txt
echo SHP %($Shipping)% 1 ? >> writeIIF.txt
echo DISC %($Discount)% 1 ? >> writeIIF.txt
echo Comm %($ServiceFee)% 1 ? >> writeIIF.txt
:LINEWRITE
IF /i %($ProductIdentifier)% equ PH-1 goto WRITE_DEFA ELSE goto WRITE_DISC
echo %($ProductIdentifier)%
:WRITE_DISC
::writes discounted prices parsed from custom variable:
echo %($ProductIdentifier)% %($Price_Each)% %($Quantity)% ? >> writeIIF.txt
goto :EOF
:WRITE_DEFA
:writes default prices parsed from Product data
echo %($ProductIdentifier)% %($UnitPrice)% %($Quantity)% ? >> writeIIF.txt
goto :EOF
:: 3-second delay
:: TYPE NUL | CHOICE.COM /N /CY /TY,3 >NUL
:EOF
You have an extra double quote at the end, which is adding it back to the end of the string (after removing both quotes from the string).
Input:
set widget="a very useful item"
set widget
set widget=%widget:"=%
set widget
Output:
widget="a very useful item"
widget=a very useful item
Note: To replace Double Quotes " with Single Quotes ' do the following:
set widget=%widget:"='%
Note: To replace the word "World" (not case sensitive) with BobB do the following:
set widget="Hello World!"
set widget=%widget:world=BobB%
set widget
Output:
widget="Hello BobB!"
As far as your initial question goes (save the following code to a batch file .cmd or .bat and run):
#ECHO OFF
ECHO %0
SET BathFileAndPath=%~0
ECHO %BathFileAndPath%
ECHO "%BathFileAndPath%"
ECHO %~0
ECHO %0
PAUSE
Output:
"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"
C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd
"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"
C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd
"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"
Press any key to continue . . .
%0 is the Script Name and Path.
%1 is the first command line argument, and so on.
Your conclusion (1) sounds wrong. There must be some other factor at play.
The problem of quotes in batch file parameters is normally solved by removing the quotes with %~ and then putting them back manually where appropriate.
E.g.:
set cmd=%~1
set params=%~2 %~3
"%cmd%" %params%
Note the quotes around %cmd%. Without them, path with spaces won't work.
If you could post your entire batch code, maybe more specific answer could be made.
I usually just remove all quotes from my variables with:
set var=%var:"=%
And then apply them again wherever I need them e.g.:
echo "%var%"
Spent a lot of time trying to do this in a simple way.
After looking at FOR loop carefully, I realized I can do this with just one line of code:
FOR /F "delims=" %%I IN (%Quoted%) DO SET Unquoted=%%I
Example:
#ECHO OFF
SET Quoted="Test string"
FOR /F "delims=" %%I IN (%Quoted%) DO SET Unquoted=%%I
ECHO %Quoted%
ECHO %Unquoted%
Output:
"Test string"
Test string
The simple tilde syntax works only for removing quotation marks around the command line parameters being passed into the batch files
SET xyz=%~1
Above batch file code will set xyz to whatever value is being passed as first paramter stripping away the leading and trailing quotations (if present).
But, This simple tilde syntax will not work for other variables that were not passed in as parameters
For all other variable, you need to use expanded substitution syntax that requires you to
specify leading and lagging characters to be removed. Effectively we are instructing to remove strip away the first and the last character without looking at what it actually is.
#SET SomeFileName="Some Quoted file name"
#echo %SomeFileName% %SomeFileName:~1,-1%
If we wanted to check what the first and last character was actually quotation before removing it, we will need some extra code as follows
#SET VAR="Some Very Long Quoted String"
If aa%VAR:~0,1%%VAR:~-1%aa == aa""aa SET UNQUOTEDVAR=%VAR:~1,-1%
I learned from this link, if you are using XP or greater that this will simply work by itself:
SET params = %~1
I could not get any of the other solutions here to work on Windows 7.
To iterate over them, I did this:
FOR %%A IN (%params%) DO (
ECHO %%A
)
Note: You will only get double quotes if you pass in arguments separated by a space typically.
This sounds like a simple bug where you are using %~ somewhere where you shouldn't be. The use if %~ doesn't fundamentally change the way batch files work, it just removes quotes from the string in that single situation.
All the answers are complete. But Wanted to add one thing,
set FirstName=%~1
set LastName=%~2
This line should have worked, you needed a small change.
set "FirstName=%~1"
set "LastName=%~2"
Include the complete assignment within quotes. It will remove quotes without an issue. This is a prefered way of assignment which fixes unwanted issues with quotes in arguments.
set widget="a very useful item"
set widget
widget="a very useful item"
set widget=%widget:"=%"
set widget
set widget=a very useful item"
The trailing quote " in line 4 is adding a quote " to the string. It should be removed.
The syntax for line 4 ends with %
I thought I had the solution, but I soon experienced unusual behavior with execution of batch files. Suddenly CMD is no recognizing long path statments. Normal execution of batch file from full path
C:\Documents and Settings\Administrator\My Documents\Txt\batchtest\dataout.bat
returns
'C:\Documents' is not recognized as an internal or external command....
There's your whole problem. CMD doesn't understand spaces inside of filenames from the command line, so it thinks you're trying to pass
and Settings\Administrator\My Documents\Txt\batchtest\dataout.bat
as parameters to the
"C:\Documents"
program.
You need to quote it to run a batch file with spaces in the path:
> "C:\Documents and Settings\Administrator\My Documents\Txt\batchtest\dataout.bat"
would have worked.
#echo off
Setlocal enabledelayedexpansion
Set 1=%1
Set 1=!1:"=!
Echo !1!
Echo "!1!"
Set 1=
Demonstrates with or without quotes reguardless of whether original parameter has quotes or not.
And if you want to test the existence of a parameter which may or may not be in quotes, put this line before the echos above:
If '%1'=='' goto yoursub
But if checking for existence of a file that may or may not have quotes then it's:
If EXIST "!1!" goto othersub
Note the use of single quotes and double quotes are different.
Azure devops sometimes uses double quoting character (") to specify string. Powershell can use single quote character (') to specify string. Naturally I wanted to have a flexibility to be able to specify parameters however I wish, so same parameter can be used from both - command line - via batch file, and as a powershell script, as any parameter, including empty value.
Quote natural thinking is to write something like this:
build.bat:
#echo off
setlocal enabledelayedexpansion
set args=%*
set args=%args:"='%
echo powershell -executionpolicy bypass "%~dpn0.ps1" %args%
endlocal
But like you can guess - this does not work out of box - if no arguments are provided to batch file so %* == empty string. args expands as no string, and next replacement notices that args is not set - and instead of replacing string - it would append extra "=' garbage to args parameter.
Solution to this was just to add extra space in first assignment.
build.bat:
#echo off
setlocal enabledelayedexpansion
set args=%*
set args=%args:"='%
echo powershell -executionpolicy bypass "%~dpn0.ps1" %args%
endlocal
After this character translation should be correct:
C:\test>build
powershell -executionpolicy bypass "C:\test.ps1"
C:\test>build aa
powershell -executionpolicy bypass "C:\test\build.ps1" aa
C:\test>build "aa"
powershell -executionpolicy bypass "C:\test\build.ps1" 'aa'
C:\test>build 'aa'
powershell -executionpolicy bypass "C:\test\build.ps1" 'aa'