Batch file add/remove hosts file entries syntax error - dos

The following script is supposed to manage adding and removing entries into the hosts file. Entries with .dev are supposed to point to localhost and all others should prompt for an IP address. If the entry already exists it should ask you if you want to remove it.
I am getting a vague The syntax of the command is incorrect error but I'm not sure which line it's referring to. If I turn #echo on it then spits out if ( on the next line and then dies. The only way I can catch the error is to do a screenshot because it immediately exits.
I've spent several hours on this, so any assistance would be greatly appreciated!
#echo off
title ClearSight Studio
echo Virtual website setup script
echo Version 1.4
echo Last modified 12/30/2011
echo.
REM Get the name of the domain name
echo What domain name? Ctrl+C to cancel. Example: newdomain.dev.
set /p domain= Domain:
REM Set a variable for the Windows hosts file location
set hostpath=\windows\system32\drivers\etc
set hostfile=hosts
set sitespath=\clearsight\sites
set extension=%domain:~-3%
REM Make the hosts file writable
attrib -r %hostpath%\%hostfile%
REM Add the domain to point to localhost at the end of the file if it doesn't already have an entry.
find /c " %domain%" %hostpath%\%hostfile%
if errorlevel 1 (
if /i %extension%==dev (
set /p ip= What is the IP?
)
echo. >> %hostpath%\%hostfile%
echo.# Adding %domain% via batch process on %date:~10,4%-%date:~4,2%-%date:~7,2%. >> %hostpath%\%hostfile%
if %ip% (
echo.%ip% %domain% >> %hostpath%\%hostfile%
) else (
echo.127.0.0.1 %domain% >> %hostpath%\%hostfile%
)
) else if errorlevel 0 (
echo Entry found in hostfile already. Would you like to remove it?
set /p remove= Remove (Y/N)
if /i %remove%==Y (
findstr /v "%domain%" %hostpath%\%hostfile% > %hostpath%\%hostfile%
)
)
if /i %extension%==dev (
REM Create the folder if it doesn't exist
if exist %sitespath%\%domain% (
echo %sitespath%\%domain% already exists.
) else (
echo Creating %sitespath%\%domain%...
mkdir %sitespath%\%domain%
)
)
REM Clean up
attrib +r %hostpath%\%hostfile%
echo.
echo Done.
if /i %extension%==dev (
REM Do a "git" of the repo, if requested
echo Would you like to clone an external git repository named %domain% from Bitbucket?
echo This assumes the git repository was set up under the "jamonholmgren" account.
echo Do it manually if it's under someone else's account. Also, make sure you have permissions to this repo.
set /p getgit= Get git clone? (Y/N):
)
REM
if /i %getgit%==Y (
git clone git#bitbucket.org:jamonholmgren/%domain%.git %sitespath%\%domain%\
pause
) else (
echo Okay, then we're done.
pause
)

You have two problems with this bit of code
if %ip% (
echo.%ip% %domain% >> %hostpath%\%hostfile%
) else (
It is invalid syntax. I presume you want to test if the variable is defined. The proper syntax is if defined ip (
You are attempting to expand %ip% in the same if() block where it was defined. This can't work because %ip% is expanded at parse time, which is before you assign the value! The solution is to use delayed expansion instead !ip!. Delayed expansion must first be enabled, probably near the top of your script, using setlocal enableDelayedExpansion
So the fixed code would look something like this
setlocal enableDelayedExpansion
.
.
.
if defined ip (
echo.!ip! %domain% >> %hostpath%\%hostfile%
) else (
You have the same delayed expansion issue with %remove%
Edit - expanding on Andriy M's comment
You also have a potential issue with how you deal with user input for ip and remove. Both values should be initialized either to nothing, or to a default value, prior to prompting for the value. If the user does not enter anything, then the existing default value (if any) is preserved.
Also, you may want to confirm that a valid value was entered, especially for the ip. If you do, then you will want to take the prompt out of the loop and put it in a called subroutine. The subroutine can check if a value was entered and loop back to try again if it wasn't. It must be in a subroutine because you cannot GOTO within a parenthesized block of code like you have with your IF statement.

When you expand a variable value via %variable% its value is expanded just once after the line that contain commands is read and before the commands are executed. For example:
set var=Original
set var=New & echo %var%
Previous line show "Original". The same effect happen with any command enclosed in parentheses (that belong to any IF or FOR commands).
The way to solve this problem is using Delayed Variable Expansion by enclosing a variable in exclamation marks instead percents:
set var=Original
set var=New & echo !var!
However, you must first activate the delayed expansion with this command:
setlocal EnableDelayedExpansion
So, insert previous line at beginning of your program and change ALL references to variables that may change its value inside an IF or FOR by !name! instead of %name%. For example:
if %ip% (
that I'm sure is the line that caused your problem...

Thanks everyone for the help! Here is the final (working) result in case anyone ever wants to do something similar. The output to the screen could probably use a little tweaking but in all my testing it seems completely reliable.
#echo off
setlocal enableDelayedExpansion
title ClearSight Studio
echo Virtual website setup script
echo Version 1.5
echo Last modified 2/23/2012
echo.
REM Get the name of the domain name
echo What domain name? Ctrl+C to cancel. Example: newdomain.dev.
set /p domain= Domain:
REM Set a variable for the Windows hosts file location
set hostpath=\windows\system32\drivers\etc
set hostfile=hosts
set sitespath=\clearsight\sites
set extension=%domain:~-3%
REM Make the hosts file writable
attrib -r %hostpath%\%hostfile%
REM Add the domain to point to localhost at the end of the file if it doesn't already have an entry.
find /c " %domain%" %hostpath%\%hostfile%
if errorlevel 1 (
if /i NOT %extension%==dev (
set /p ip= What is the IP?
) else (
set ip=127.0.0.1
)
echo. >> %hostpath%\%hostfile%
echo.# Adding %domain% via batch process on %date:~10,4%-%date:~4,2%-%date:~7,2%. >> %hostpath%\%hostfile%
echo.!ip! %domain% >> %hostpath%\%hostfile%
) else if errorlevel 0 (
echo Entry found in hostfile already.
set /p remove= Would you like to remove it? (Y/N)
if /i !remove!==Y (
findstr /v %domain% %hostpath%\%hostfile% > %hostpath%\%hostfile%.txt
type %hostpath%\%hostfile%.txt > %hostpath%\%hostfile%
)
)
if /i %extension%==dev (
REM Create the folder if it doesn't exist
if exist %sitespath%\%domain% (
echo %sitespath%\%domain% already exists.
) else (
echo Creating %sitespath%\%domain%...
mkdir %sitespath%\%domain%
)
)
REM Clean up
attrib +r %hostpath%\%hostfile%
REM Flush DNS so the changes are available imidiately
ipconfig /flushdns
echo.
echo Done.
if /i %extension%==dev (
REM Do a "git" of the repo, if requested
echo Would you like to clone an external git repository named %domain% from Bitbucket?
echo This assumes the git repository was set up under the "jamonholmgren" account.
echo Do it manually if it's under someone else's account. Also, make sure you have permissions to this repo.
set /p getgit= Get git clone? (Y/N)
)
REM
if /i !getgit!==Y (
git clone git#bitbucket.org:jamonholmgren/%domain%.git %sitespath%\%domain%\
pause
) else (
echo Okay, then we're done.
pause
)

Just some hints for debugging the batch file:
Start it from a cmd shell to avoid closing the window after exiting
Add more REM commands that will serve as log entries when turning echo on
Simplify your script by repeatedly removing parts from the end until it runs without error. Reinsert the faulty parts and try to figure out what's wrong there
While this does not quite answer your question, I hope the hints will help you solve the problem. You are always welcome to ask for general advice, but I'm afraid that your particular problem is somehow a bit too specific to be of general interest.

Related

If statement ( was unexpected at this time

I have a bundled if statement that checks whether java is installed and whether or not i'm at college or at home it is part of a larger piece of code but doesn't work on its own either any help would be much appreciated
Triple Checked i have the right number of brackets and equals signs and making sure no obvious mistakes were made so i'm confused as to what has gone wrong
if exist 'C:\Temporary Workspace' (set installtype=College)
where java >nul 2>nul
pause
if %errorlevel%==1 (
if %installtype%==College (
goto :college
) else (
set /P javaboolean=Java was not found is java installed? (Y/N)
if %javaboolean%==Y (
echo Please enter the path to java.exe
set /P javalocation=e.g. C:\Program Files\Common Files\Oracle\Java\javapath\java.exe
)
)
)
pause
exit
:college
echo success for college detection
pause
The error message and run time:
D:\Batch Testing>echo Checking Location...
Checking Location...
D:\Batch Testing>if exist 'C:\Temporary Workspace' (set installtype=College)
D:\Batch Testing>where java 1>nul 2>nul
D:\Batch Testing>pause
Press any key to continue . . .
( was unexpected at this time.
I expect the output to be 'success for college detection' as the directory does exist
you need to change your ifs a little bit
the first could be changed to
if exist "C:\Temporary Workspace" set installtype=College
note that the single apostrophe is not a valid quotation mark in windows cmd. And you can remove your parentheses because they are not needed.
the second could be written as
if errorlevel 1 (
because errorlevel is not %errorlevel% (for a detailed explanation, read https://devblogs.microsoft.com/oldnewthing/20080926-00/?p=20743 )
and the last could be
if .%installtype%==.College (
because when installtype is blank the if instruction makes no sense and produces syntax error; inserting the two . avoids it.
... and, as a bonus, you might want to consider to use if /i to ignore case when comparing, so College, college, COLLEGE or even cOllegE would match.
Well, there are several issues in your code. The line
if exist 'C:\Temporary Workspace' (set installtype=College)
will never set the variable installtype, because this checks whether 'C:\Temporary exists, which does not, since the apostrope ' is just an ordinary character for the Windows Command Prompt cmd. To make it work you must use quotation marks ":
if exist "C:\Temporary Workspace\" (set "installtype=College")
The trailing \ lets the condition check for existence of a directory called Temporary Workspace but not for a file with that name.
Note that I used the quoted set syntax here, which is generally recommended as it protects special characters.
The condition
if %installtype%==College (
will return a syntax error, because the variable installtype has not been set before (due to the wrong syntax you used). To avoid trouble with empty variables, quote both comparison expressions:
if "%installtype%"=="College" (
This is also described in this thread.
The command
set /P javaboolean=Java was not found is java installed? (Y/N)
will fail when in a parenthesised block of code, because the ) will unintentionally be recognised by cmd and close the block at an undesired position. Again use quotation to solve that:
set /P javaboolean="Java was not found is java installed? (Y/N)"
or:
set /P "javaboolean=Java was not found is java installed? (Y/N)"
However, the condition
if %javaboolean%==Y (
will still fail, because the queried variable javaboolean is set in the same block of code, so the returned value is the one present when the entire block is parsed, which is an empty string most probably. To overcome this, you must apply delayed variable expansion.
Put this somewhere before to enable delayed expansion:
setlocal EnableDelayedExpansion
Then replace the %-signs by exclamation marks ! (as you can see I again applied quotation here):
if "!javaboolean!"=="Y" (
Then put this somewhere after to end the environment localisation introduced by setlocal:
endlocal
Regard that all environment changes (variables, current directories) after setlocal are lost after endlocal and the state before setlocal becomes restored.
A similar problem is also described in this question and solved by this answer.
Instead of set /P just for a Yes/No decision consider to use the choice command, which does not allow to enter anything else:
rem /* The default choices are `Y` and `N`;
rem `choice` sets `ErrorLevel` to `1` when pressing `Y` and to `2` when pressing `N`: */
choice /M "Java was not found is java installed"
rem // The following means: if ErrorLevel >= 1 and if ErrorLevel < 2:
if ErrorLevel 1 if not ErrorLevel 2 (echo Yes has been chosen.)
Instead of
exit
you should use
exit /B
to only terminate the batch script but keep the hosting cmd instance alive. This is particularly helpful when you execute the batch file from a Command Prompt window rather than by double-clicking its icon in Explorer as you can view the console output then.
Instead of the string comparison
if %errorlevel%==1 (
you could also do true numeric comparison like
if %errorlevel% equ 1 (
or, if you are fine with the condition to be true if ErrorLevel is also greater than one,
if ErrorLevel 1 (
Alternatively, you could even use condition execution operators, which query the exit code:
where java > nul 2>&1 && (
rem // The code here is executed when `where` succeeds.
) || (
rem // The code here is executed when `where` fails.
)
So finally, here is the fixed script:
Code based on yours:
if exist "C:\Temporary Workspace\" (set "installtype=College")
where java > nul 2>&1
pause
if ErrorLevel 1 (
if "%installtype%"=="College" (
goto :college
) else (
set /P javaboolean="Java was not found is java installed? (Y/N) "
setlocal EnableDelayedExpansion
if "!javaboolean!"=="Y" (
endlocal
echo Please enter the path to java.exe
set /P javalocation="e.g. C:\Program Files\Common Files\Oracle\Java\javapath\java.exe "
) else endlocal
)
)
pause
exit /B
:college
echo success for college detection
pause
Variant using conditional execution (||) and the choice command:
if exist "C:\Temporary Workspace\" (set "installtype=College")
where java > nul 2>&1 || (
if "%installtype%"=="College" (
goto :college
) else (
choice /M "Java was not found is java installed"
if ErrorLevel 1 if not ErrorLevel 2 (
echo Please enter the path to java.exe
set /P javalocation="e.g. C:\Program Files\Common Files\Oracle\Java\javapath\java.exe "
)
)
)
pause
exit /B
:college
echo success for college detection
pause

Checking for a file on remote computers via Batch file

So I have set up an MSI software installation to happen on startup, however, i have noticed certain machines for whatever reason are not installing the package. I followed Microsoft's setup on the MSI install so everything in theory should be fine.
What I want to do is check to see if a specific file is located on a machine or not. I have created a txt file with all of the machines IP addresses and i have tried a for each loop to run through the IP's in the text file and if it exists to output to a log file.
The problem I am running into however, is that all are returning as if the file does not exist and echoing out the else command into my log file. I know for a fact the majority of these IP's (computers) have the file in the directory I specified.
Edit: now it gets stuck if that IP isn't there (I.E. the computer is turned off). Is there anyway to check for that?
ECHO ON
for /F %%a in (ips.txt) do (
set host=%%a
if exist \\%host%\c$\ProgramData\dvsAnalytics\Encore\Config\Encore.ScreenRecording.ClientService.exe.config (
rem file exists
ECHO %%a>>"C:\some location\encore-install-success.log"
) else (
rem file does not exist
ECHO %%a>>"C:\some location\encore-install-fail.log"
)
)
pause
There is no need to use an interim variable host to hold the value of %%a, simply use %%a directly:
for /F %%a in (ips.txt) do (
if exist "\\%%a\c$\ProgramData\dvsAnalytics\Encore\Config\Encore.ScreenRecording.ClientService.exe.config" (
rem ...rest of your code...
)
)
If you insist on the interim variable, you need to use delayed expansion for it as it is set and read in the same block of code; otherwise, you will read the value present when the entire block is parsed. The changed code would look like this:
setlocal EnableDelayedexpansion
for /F %%a in (ips.txt) do (
set "host=%%a"
if exist "\\!host!\c$\ProgramData\dvsAnalytics\Encore\Config\Encore.ScreenRecording.ClientService.exe.config" (
rem ...rest of your code...
)
)
endlocal
In addition, there is a trailing space after set host=%%a in the code in your question; if it is also present in your actual scipt, it becomes part of the variable value and will most likely disturb; to avoid that, the syntax set "host=%%a" should be used.
To check whether a host is available in advance you could use the ping command.
This works reliably for IPv4 addresses:
ECHO ON
for /F %%a in (ips.txt) do (
ping -n 1 -4 %%a 2> nul | find "TTL=" > nul && (
if exist "\\%%a\c$\ProgramData\dvsAnalytics\Encore\Config\Encore.ScreenRecording.ClientService.exe.config" (
rem file exists
ECHO %%a>>"C:\some location\encore-install-success.log"
) else (
rem file does not exist
ECHO %%a>>"C:\some location\encore-install-fail.log"
)
)
)
pause
And this is for IPv6 addresses:
ECHO ON
for /F %%a in (ips.txt) do (
ping -n 1 -6 %%a > nul 2>&1 && (
rem ...rest of your code...
)
)
pause

How do you make a batch file check for duplicate batch files?

How do you check for already existing batch files in batch script?
I'm working on a batch RPG game where you can log in or create an account. I have successfully been able to set up a code that notifies the user when the username has a space in it, and how it can't be used, but I'm stumped at how it could be done to check for a duplicate batch file. For example, I already have a username called "Test", and I would like to make another username called "Test"...
Here is a copy of my code for the no spaces script:
:createuser
echo.
echo What would you like your Username to be?
set /p username1=
set v1f=0
:checkforspaces
set x=!v1f!
set Letter%v1f%=!username1:~%x%,1!
if "!Letter%v1f%!" EQU " " (
echo.
echo.
echo Sorry you cant use spaces in your Username.
pause>nul
goto entergame
)
if NOT "!Letter%v1f%!" EQU "" (
set /a v1f=%v1f%+1
goto checkforspaces
)
echo.
echo What would you like your Password to be?
set /p password1=
goto DATA_VALUES
To check for spaces in var:
echo %var%|find " " >nul
if errorlevel 1 (echo no spaces) else (echo spaces found)
to check whether the filename var exists:
if exist %var%.ext (echo file %var%.ext exists) else (echo file %var%.ext not found)
btw - an easy-peasy game-save routine is
set>%var%.ext
and reload is
for /f "delims=" %%a in (%var%.ext) do set %%a
note that var above can be any variable-name and .ext your chosen file extension.

Batch script prompt needs multiple entries

So I have this subroutine that I want to call from another location in a batch file. The functions work as desired, but for some reason I cant pin down, the prompt wants to have the user enter something TWICE, before it will accept anything.
Say, if I enter "0", to go back to a previous menu, it takes me right back to the prompt, and I have to enter "0" again before it will actually go back to the previous menu (elsewhere in my main script).
I can, say, enter "w" (or any other value), then the second time, enter the one I actually WANT to use, and it will finally do it.
This is driving me nuts.
:subfullbackup
cls
if exist "%current%\Backup\Full_Backup" (
Echo Backup folder already exists
Echo.
Echo [o] Overwrite local device files with existing local files
Echo [w] Wipe current local backup and start fresh
Echo.
set /p choice=Select:
if %choice% == o (
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto :backup
)
if %choice% == w (
Echo.
Echo Removing all current local backup files in 'Full_Backup'
rmdir /S /Q "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto :backup
)
if not %choice% == o goto subfullbackup
if not %choice% == w goto subfullbackup
) else (
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto :backup
)
Goto :eof
Your batch code with using delayed expansion, enabled at top of the batch script with command setlocal which additionally creates a copy of all environment variables and remembering also current directory for restoring the variables list, current directory and current states of command extensions and delayed expansion on endlocal or leaving batch processing:
#echo off
setlocal EnableDelayedExpansion
set "current=%CD%"
:FullBackup
cls
if exist "%current%\Backup\Full_Backup" (
Echo Backup folder already exists
Echo.
Echo [o] Overwrite local device files with existing local files
Echo [w] Wipe current local backup and start fresh
Echo.
set "UserChoice="
set /p "UserChoice=Select: "
if /I "!UserChoice!" == "o" (
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb.exe pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto DoBackup
)
if /I "!UserChoice!" == "w" (
Echo.
Echo Removing all current local backup files in 'Full_Backup'
rmdir /S /Q "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb.exe pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto DoBackup
)
goto FullBackup
) else (
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb.exe pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto DoBackup
)
Goto :EOF
:DoBackup
But your batch code could be also written without delayed expansion and much more compact avoiding duplicate code lines:
#echo off
set "current=%CD%"
:FullBackup
cls
if exist "%current%\Backup\Full_Backup" goto PromptBackup
:OverwriteBackup
Echo.
Echo Depending on how much data you have,
Echo this could take a couple hours.
Echo.
Echo Backing up...
adb.exe pull /sdcard/ "%current%\Backup\Full_Backup" >nul 2>&1
Echo.
Echo -= BACKUP COMPLETE =-
Pause
Goto DoBackup
:PromptBackup
Echo Backup folder already exists
Echo.
Echo [o] Overwrite local device files with existing local files
Echo [w] Wipe current local backup and start fresh
Echo.
set "UserChoice="
set /p "UserChoice=Select: "
if /I "%UserChoice%" == "o" goto OverwriteBackup
if /I not "%UserChoice%" == "w" goto FullBackup
Echo.
Echo Removing all current local backup files in 'Full_Backup'
rmdir /S /Q "%current%\Backup\Full_Backup" >nul 2>&1
goto OverwriteBackup
:DoBackup
Some notes about small changes in code:
choice (SS64 article) is a standard Windows command. Therefore it is advisable to avoid choice (Microsoft article) as name for an environment variable or label. UserChoice (CamelCase spelling for easier reading) is used instead of choice.
backup (SS64 article) is not a standard Windows command, but a standard SQL command. Therefore it is also advisable to avoid backup as name for an environment variable or label. DoBackup is used instead in batch code above.
It is advisable to define a default for an environment variable before prompting a user. The user can hit just RETURN or ENTER in which case the environment variable keeps its value.
The environment variable is cleared with set "UserPoint=" before prompting the user and therefore the variable does not exist when user enters nothing.
Possible would be also set "UserPoint=o" or set "UserPoint=w" to define a valid default value.
Comparing strings with user input should be done always with using double quotes to avoid an exit of batch processing caused by a syntax error when user inputs nothing.
if %choice% == w ( becomes if == w ( when the user enters nothing which is a syntax error and results in breaking batch processing by command processor.
if /I "%UserChoice%" == "w" ( becomes if /I "" == "w" when the user enters nothing in code above which is still valid batch code and can be therefore processed.
Note: User could now break batch processing by entering "w".
But it can be expected here that the user does not input 1 or more double quotes on being asked for o or w.
On comparing strings entered by user with predefined strings it is advisable to do case-insensitive string comparisons if letters are included in the compared strings.
The option /I changes a string comparison from case-sensitive to case-insensitive.
So now the user can enter also O or W and this is interpreted like o or w.

Variable not getting set correctly in a dos batch file on XP

I am trying to write a batch file to be run in a command prompt on XP. I am trying to get a listing of files in a specific path that follow a certain naming convention. I need to copy and rename each file instance to a static name and drop it to a transmission folder.
Since it may take a little while for the file to go in the transmission folder, I need to check before I copy the next file over so that I don't overlay the previous file. I am not able to use SLEEP or TIMEOUT since I don't have the extra toolkit installed. I try to just continually loop back to a START section until the file is sent.
I noticed that if I passed the %%x value set in the for loop that if I loop back to the START section a couple of times, it seems to lose its value and it is set to nothing. So I tried to set a variable to hold the value.
I seem to be having issues with the variable not being set correctly or not cleared. Originally it kept on referencing the first file but now it doesn't seem to be set at all. The ECHO displays the correct the value but the filename variable is empty still.
Does anyone know a better way of doing this? Thanks in advance for your help as I have already wasted a whole day on this!
This is the batch file:
#ECHO "At the start of the loop"
#for %%x in (C:\OUTBOUND\customer_file*) do (
#ECHO "In the loop"
#ECHO "loop value ="
#ECHO %%x
SET filename=%%x
#ECHO "filename ="
#ECHO %filename%
#ECHO ...ARCHIVE OUTBOUND CUSTOMER FILE
archivedatafile --sourcefile="%filename%" --archivefolder="..\archivedata\customer" --retentiondays=0
IF NOT %ERRORLEVEL%==0 GOTO ERROR
PAUSE
:START
IF EXIST l:\OutputFile (
#ping 1.1.1.1 -n 1 -w 30000
GOTO START
) ELSE (
COPY %filename% l:\OutputFile /Y
IF NOT %ERRORLEVEL%==0 GOTO ERROR
PAUSE
)
)
GOTO END
:ERROR
#echo off
#ECHO *************************************************************
#ECHO * !!ERROR!! *
#ECHO *************************************************************
:END
SET filename=
foxidrive has provided a script that should work, but did not provide an explanation as to why your code fails and how he fixed the problems.
You have 2 problems:
1) Your FOR loop is aborted immediately whenever GOTO is executed within you loop. It does not matter where the GOTO target label is placed - GOTO always terminates a loop. Foxidrive's use of CALL works perfectly - the loop will continue once the CALLed routine returns.
2) You attempt to set a variable within a block of code and then reference the new value within the same block. %VAR% is expanded when the statement is parsed, and complicated commands like IF and FOR are parsed once in their entirety in one pass. Actually, any block of code within parentheses is parsed in one pass. So the values of %ERRORLEVEL% and %FILENAME% will be constant - the values that existed before the block was entered.
As Endoro has indicated, one way to solve that problem is to use delayed expansion. Delayed expansion must be enabled by using setlocal enableDelayedExpansion, and then expand the variable using !VAR!. The value is expanded at execution time instead of parse time. Type HELP SET from the command prompt for more information about delayed expansion.
But beware that delayed expansion can cause its own problems when used with a FOR loop because the delayed expansion occurs after the FOR variable expansion: %%x will be corrupted if the value contains a !. This problem can be solved by carefully toggling delayed expansion ON and OFF as needed via SETLOCAL and ENDLOCAL.
Foxidrive's code avoids the entire delayed expansion issue by using CALL. His :NEXT routine is not inside a FOR loop, so all the commands are reparsed each time it is called, so delayed expansion is not required.
This may work - it is untested:
#echo off
ECHO Starting...
for %%x in (C:\OUTBOUND\customer_file*) do call :next "%%x"
echo done
pause
goto :eof
:next
ECHO ...ARCHIVING OUTBOUND CUSTOMER FILE "%~1"
archivedatafile --sourcefile="%~1" --archivefolder="..\archivedata\customer" --retentiondays=0
IF ERRORLEVEL 1 GOTO :ERROR
:loop
echo waiting for file...
ping -n 6 localhost >nul
IF EXIST l:\OutputFile GOTO :loop
COPY "%~1" l:\OutputFile /Y
IF ERRORLEVEL 1 GOTO :ERROR
GOTO :EOF
:ERROR
ECHO *************************************************************
ECHO * !!ERROR!! in "%%x"
ECHO *************************************************************
pause
goto :EOF
try this:
#echo off&setlocal
for %%x in (C:\OUTBOUND\customer_file*) do SET "filename=%%x"
ECHO %filename%
ECHO ...ARCHIVE OUTBOUND CUSTOMER FILE
archivedatafile --sourcefile="%filename%" --archivefolder="..\archivedata\customer" --retentiondays=0
IF NOT %ERRORLEVEL%==0 GOTO:ERROR
PAUSE
:START
IF EXIST l:\OutputFile ping 1.1.1.1 -n 1 -w 30000&GOTO:START
COPY "%filename%" l:\OutputFile /Y
IF NOT %ERRORLEVEL%==0 GOTO:ERROR
PAUSE
GOTO:END
:ERROR
echo off
ECHO *************************************************************
ECHO * !!ERROR!! *
ECHO *************************************************************
:END
SET "filename="
If you use codeblocks (if and for with ( )) and variables with changing values you have to enable delayed expansion. You don't need code blocks in this code, as you can see.

Resources