How do I request and receive user input in a .bat and use it to run a certain program? - input

This is what I have so far
#echo off
:Ask
echo Would you like to use developer mode?(Y/N)
set INPUT=
set /P INPUT=Type input: %=%
If %INPUT%=="y" goto yes
If %INPUT%=="n" goto no
If %INPUT%=="Y" goto yes
If %INPUT%=="N" goto no
:yes
java -jar lib/RSBot-4030.jar -dev
echo Starting RSbot in developer mode
:no
java -jar lib/RSBot-4030.jar
echo Starting RSbot in regular mode
pause
Either way if the user enters y or n it always runs in -dev mode.
How do I make it run in -dev mode if the answer is yes, and regular mode if the answer is no. Also, how do I make it ask again if the input isn't Y, N, y, or n?

If the input is, say, N, your IF lines evaluate like this:
If N=="y" goto yes
If N=="n" goto no
…
That is, you are comparing N with "y", then "n" etc. including "N". You are never going to get a match unless the user somehow decides to input "N" or "y" (i.e. either of the four characters, but enclosed in double quotes).
So you need either to remove " from around y, n, Y and N or put them around %INPUT% in your conditional statements. I would recommend the latter, because that way you would be escaping at least some of the characters that have special meaning in batch scripts (if the user managed to type them in). So, this is what you should get:
If "%INPUT%"=="y" goto yes
If "%INPUT%"=="n" goto no
If "%INPUT%"=="Y" goto yes
If "%INPUT%"=="N" goto no
By the way, you could reduce the number of conditions by applying the /I switch to the IF statement, like this:
If /I "%INPUT%"=="y" goto yes
If /I "%INPUT%"=="n" goto no
The /I switch makes the comparisons case-insensitive, and so you don't need separate checks for different-case strings.
One other issue is that, after the development mode command is executed, there's no jumping over the other command, and so, if the user agrees to run Java in the development mode, he'll get it run both in the development mode and the non-development mode. So maybe you need to add something like this to your script:
...
:yes
java -jar lib/RSBot-4030.jar -dev
echo Starting RSbot in developer mode
goto cont
:no
java -jar lib/RSBot-4030.jar
echo Starting RSbot in regular mode
:cont
pause
Finally, to address the issue of processing incorrect input, you could simply add another (unconditional) goto command just after the conditional statements, just before the yes label, namely goto Ask, to return to the beginning of your script where the prompt is displayed and the input is requested, or you could also add another ECHO command before the jump, explaining that the input was incorrect, something like this:
#echo off
:Ask
echo Would you like to use developer mode?(Y/N)
set INPUT=
set /P INPUT=Type input: %=%
If /I "%INPUT%"=="y" goto yes
If /I "%INPUT%"=="n" goto no
echo Incorrect input & goto Ask
:yes
...
Note: Some of the issues mentioned here have also been addressed by #xmjx in their answer, which I fully acknowledge.

i just do :
set /p input= yes or no
if %input%==yes echo you clicked yes
if %input%==no echo you clicked no
pause

Here is a working example:
#echo off
:ask
#echo echo Would you like to use developer mode?(Y/N)
set INPUT=
set /P INPUT=Type input: %=%
If /I "%INPUT%"=="y" goto yes
If /I "%INPUT%"=="n" goto no
goto ask
:yes
#echo you select yes
goto exit
:no
#echo you select no
goto exit
:exit
#pause

I have improved batch file with yes or no prompt. If user enter any character except y and n , then it will again prompt user for valid input. It Works for me.
#echo off
:ConfirmBox
set /P c= Are you sure want to contine (y/n)?
if /I "%c%" EQU "Y" (
goto :FnYes
) else if /I "%c%" EQU "N" (
goto :FnNo
) else (
goto :InValid
)
:FnYes
echo You have entered Y
goto :END
:FnNo
echo You have entered N
goto :END
:InValid
echo Invalid selection. Enter Y or N
goto :ConfirmBox
:END
pause
exit
/I in if condition will validate both lowercase and uppercase characters.

echo off
setlocal
SET AREYOUSURE = N
:PROMPT
set /P AREYOUSURE=Update Release Files (Y/N)?
if /I %AREYOUSURE% NEQ Y GOTO END
set /P AREYOUSURE=Are You Sure you want to Update Release Files (Y/N)?
if /I %AREYOUSURE% NEQ Y GOTO END
echo Copying New Files
:END
This is code I use regularly. I have noticed in the examples in this blog that quotes are used. If the test line is changed to use quotes the test is invalid.
if /I %AREYOUSURE% NEQ "Y" GOTO END
I have tested on XP, Vista, Win7 and Win8. All fail when quotes are used.

I don't know the platform you're doing this on but I assume Windows due to the .bat extension.
Also I don't have a way to check this but this seems like the batch processor skips the If lines due to some errors and then executes the one with -dev.
You could try this by chaning the two jump targets (:yes and :no) along with the code. If then the line without -dev is executed you know your If lines are erroneous.
If so, please check if == is really the right way to do a comparison in .bat files.
Also, judging from the way bash does this stuff, %foo=="y" might evaluate to true only if %foo includes the quotes. So maybe "%foo"=="y" is the way to go.

Depending on the version of Windows you might find the use of the "Choice" option to be helpful. It is not supported in most if not all x64 versions as far as I can tell.
A handy substitution called Choice.vbs along with examples of use can be found on SourceForge under the name Choice.zip

Add quotation marks (" ") around the %INPUT% so it looks like this:
If "%INPUT%" == "y" goto yes
If "%INPUT%" == "n" goto no
If "%INPUT%" == "Y" goto yes
If "%INPUT%" == "N" goto no

try this for comparision
if "%INPUT%"=="y"...

Related

Search a string inside a spooled text file in BAT file

I am a complete beginner in bat files. I am explaining the scenario of mine requirement. Hope I will get the exact o/p from you gurus.
This is my current batch file:
Note : findstr command specified by OP in comment included in code but spacing - well, who knows? OP to edit, please
CALL %ORACLE_HOME%/bin/sqlplus "/as sysdba" #D:\Long_Running\Long_running_job.sql > D:\Long_Running\LongrunningJobs.txt
call :CheckEmpty "%file%"
powershell -ExecutionPolicy ByPass -File D:\Long_Running\Send_email_report.ps1
goto :eof
:CheckEmpty
if %~z1 == 0 exit
This basically connects SQL plus, connects as sysdba, go to location where Long_running.sql file is present and spools the o/p to LongrunningJobs.txt.
From there it triggers mails in the next line(power shell).
Requirement: If I can search for a particular string say "ABCDE" in the LongrunningJobs.txt file and if it matches then it should trigger the mail else it should not trigger mail and simply come out.
What exactly should I input? I used FINDSTR might be I didn't use it correctly, it did not go well. The mail was not triggered.
#ECHO OFF
SETLOCAL
SET "destdir=U:\destdir"
SET "outfile=%destdir%\LongrunningJobs.txt"
:: first test : empty file
COPY /y NUL "%outfile%" >NUL 2>NUL
ECHO test 1
FINDSTR "ABCDE" "%outfile%" >NUL &&ECHO Send mail
:: second test : file NOT containing "ABCDE"
ECHO something >"%outfile%"
ECHO test 2
FINDSTR "ABCDE" "%outfile%" >NUL &&ECHO Send mail
:: third test : file containing "ABCDE"
ECHO ABCDE>>"%outfile%"
ECHO test 3
FINDSTR "ABCDE" "%outfile%" >NUL &&ECHO Send mail
GOTO :EOF
I use destdir to keep from cluttering my system.
Note that send mail will only be echoed in the third case, where the subject file contains the target string.
FINDSTR "ABCDE" "%file%" >NUL && (
powershell -ExecutionPolicy ByPass -File D:\Long_Running\Send_email_report.ps1
goto :eof )
#Magoo has given the correct answer, I was calling the function which i should not have. Thanks a lot everyone.

"if" statements in batch: file crashes when the input is supposed to be a number, but instead has words with spaces

So, I have a set /p thing in a batch file. For the user to proceed, they must type "2". I can't seem to find my specific problem anywhere.
#echo off
echo "What is 1+1"
set /p oneplusone=Type Answer Here:
if %oneplusone%==2 goto correct
if %oneplusone% neq 2 goto incorrect
:correct
cls
echo Correct!
pause
goto youranswer
:incorrect
cls
echo Wrong.
pause
goto youranswer
:youranswer
cls
echo You answered: %oneplusone%
Now, if the user types a number/word with no spaces, everything works out, and it shows your answer as wanted.
However, say if you type something like "hi there" with a space, the batch file closes immediately. This only happens when the answer needs to be a number, and you type something that involves a space.
Any help?
Thanks in advance.
You can check if your answer is a number using this:
set /a test=%oneplusone%*1
if %test%==0 goto notValid
and have another label, making your code this
#echo off
echo "What is 1+1"
set /p oneplusone=Type Answer Here:
set /a test=%oneplusone%*1
if %test%==0 goto notValid
if %oneplusone%==2 goto correct
if %oneplusone% neq 2 goto incorrect
:correct
cls
echo Correct!
pause
goto youranswer
:incorrect
cls
echo Wrong.
pause
goto youranswer
:notValid
cls
echo Your input is not valid
pause
goto youranswer
:youranswer
cls
echo You answered: %oneplusone%

Something wrong with some batch file stuff, doesn't do what it should do, cant spot syntax errors

So, I am writing a computer speeder in batch, and I am baffled by this problem:
#echo off
cls
color 02
:licence
title Computer Speeder 2012 (Free licence)
cls
echo This is the free version of Computer Speeder 2012.
echo.
echo Do you wish to license this copy? [Y]es or [N]o.
choice /c NY /n
if ERRORLEVEL 2 goto license
if ERRORLEVEL 1 goto startup1
:license
dir | find "validatecode.txt" > if exist "validatecode.txt"
goto bam
) else (
goto else
:bam
cls
echo Type in your lisencing code to validate this
echo copy to upgrade to the full version:
echo.
set /p vd=""
:else
cls
echo You do not have a validation file on your computer,
echo if you purchased the full version you probably
echo deleted the file. Check the recycle bin, check you
echo put it in the correct path or re-purchase the
echo software because it has an individual code.
pause
goto startup1
For some odd reason, it executes all of this code chronologically:
First it asks if you want to license the copy of the software. If you press Y it takes you to license. It then performs the line dir | find "validatecode.txt" >if exist "validatecode.txt"
so on and so forth. However, it goes to bam and THEN goes to else. There's no other flaw in the code, I cant find any syntax error, can you guys explain what I am doing wrong? Im a noob kinda :/
If you want the program to stop after executing :bam, you should put a
goto:EOF after set /p vd=".
:bam
cls
echo Type in your lisencing code to validate this
...
set /p vd=""
goto:EOF
:else
cls
...
Try replacing this:
:lisence
dir | find "validatecode.txt" > if exist "validatecode.txt"
goto bam
) else (
goto else
with this:
:lisence
if exist "validatecode.txt" goto bam
goto else
Explanation:
You would need to test an errorlevel of the Find process for your code to possibly work, and the redirector '>' only creates a file called 'if', containing, oddly, the words exist and vaildatecode.txt.
Your DIR command will only look in the execution directory, but your 'bam' subroutine implies you intend to search the hard drive? True? If so, my 'if exist' command should be changed to:
dir /s/b validatecode.txt && goto bam
You appear to not be using information inside the file, so if you need to search the entire hard drive this command will perform it, and will logically go to the correct subroutine.
The snippet provided tests for a file called validatecode.txt in the local directory, and executes a goto to the label bam if it is found. If the file does not exist, focus drops to the next line, which performs a goto to the label :else.
You will need to finish your script differently as well. As it stands, if the validatecode.txt is found, you will be executing both 'bam' and 'else'. You should place a final label like :exit (:eof is reserved) and make a goto :exit command as the last line of each subroutine.
Finally, your call to the subroutine Startup1 will always fail because you have no label called Startup1.
From a flow standpoint, it looks like you have no way to exit if the user does not want to license the copy they are using.

DOS script to remove identical files by content

I have a directory with several thousand text files that I need to process. Some of these files are identical while others are identical except the timestamp varies by a few seconds / milliseconds. I need some way to automate the deletion of identical files and only keep one copy.
I'm thinking of something like:
while there are files in the directory still
{
get file // e.g., file0001
while (file == file + 1) // e.g., file0001 == file0002 using 'fc' command
{
delete file + 1
}
move file to another directory
}
Is something like this even possible in Microsoft Windows Server 2003's DOS?
Of course it is. Everything is possible in batch. :D
This batch doesn't actually delete files. It just echos the result of the comparison. You can delete either one of the files if you find two that are the same.
Save the code as CleanDuplicates.bat and start the program with CleanDuplicates {Folder}
Provided AS IS, without any guarantees! I don't want you knocking on my door because your entire server is messed up. ;-)
The code actually calls itself recursively. This could maybe be done in a different way but hey, it works. It also starts itself again in a new cmd, because that makes cleaning up easier. I tested the script in Windows Vista Business, but it should work on Server 2003 as well. Hey, it even has a help function. ;-)
It contains two loops that each return every file, so when you implement the actual deleting, it may report that some files don't exist, because they are deleted in an earlier iteration.
#echo off
rem Check input. //, /// and //// are special parameters. No parameter -> help.
if %1check==//check goto innerloop
if %1check==///check goto compare
if %1check==////check goto shell
if %1check==/hcheck goto help
if %1check==check goto help
rem Start ourselves within a new cmd shell. This will automatically return to
rem the original directory, and clear our helper environment vars.
cmd /c %0 //// %1
echo Exiting
goto end
:shell
rem Save the current folder, jump to target folder and set some helper vars
set FCOrgFolder=%CD%
cd %2
set FCStartPath=%0
if not exist %FCStartPath% set FCStartPath=%FCOrgFolder%\%0
rem Outer loop. Get each file and call ourselves with the first special parameter.
for %%a in (*.*) do call %FCStartPath% // "%2" "%%a"
goto end
:innerloop
rem Get each file again and call ourselves again with the second special parameter.
for %%b in (*.*) do call %FCStartPath% /// %2 %3 "%%b"
goto end
:compare
rem Actual compare and some verbose.
if %3==%4 goto end
echo Comparing
echo * %3
echo * %4
fc %3 %4 >nul
rem Get results
if errorlevel 2 goto notexists
if errorlevel 1 goto different
echo Files are identical
goto end
:different
echo Files differ
goto end
:notexists
echo File does not exist
goto end
:help
echo Compares files within a directory.
echo Usage: %0 {directory}
goto end
:end

Removing double quotes from variables in batch file creates problems with CMD environment

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'