This question already has answers here:
Variables are not behaving as expected
(1 answer)
Example of delayed expansion in batch file
(5 answers)
Closed 2 years ago.
I have developed a batch file that is designed to check a value in a given excel sheet.
And decides what to do depending of the value in the Excel sheet (value either 0 or more than zero)
Code is as follows
#echo off
setlocal EnableDelayedExpansion
cd\
D:
cscript //nologo testexcel.vbs
IF !ERRORLEVEL! EQU 1 (
taskkill /F /IM explorer.exe
*****MORE ACTIONS HERE*****
SET running=0
FOR /f "tokens=*" %%A IN ('tasklist^ /v^| findstr /i /c:"iexplore.exe"') DO SET running=1
IF %running% == 0 (
explorer.exe
)
) ELSE (
***OTHER ACTIONS HERE***
)
exit
The code will run a VBscript using the cscript command and will; return a ERROR LEVEL value, either ERROR LEVEL is 1 or otherwise. For some reason I keep getting the below error:
( was unexpected at this time.
I understand that this may be happening due to the due to all the commands and variables within those parentheses are expanded. But I am using setlocal EnableDelayedExpansion but still getting the same error.
Related
This question already has answers here:
Variables are not behaving as expected
(1 answer)
How to echo "2" (no quotes) to a file, from a batch script?
(11 answers)
How to save/load variables of a batch file game to/from a text file? [closed]
(1 answer)
Closed 1 year ago.
I have the following code to create a file if it does not exist, creating a variable (hi), echo the variable into the file, and then read the text as a variable. If it does exist, it simply reads the text as a variable:
if exist hiscore.txt (
for /f "delims=" %%x in (hiscore.txt) do set /a hi=%%x
) else (
set /a hi=0
echo %hi%>"hiscore.txt"
for /f "delims=" %%x in (hiscore.txt) do set /a hi=%%x
)
if I create the file manually, and type 0 into it manually, it works. If I delete the file, and then run this, it says "Missing Operand" and echos "ECHO is off" into the file. What can I change?
Here's a quick example which may help you:
#Echo Off
Set "hi=0"
Set /P "hi=" 0<"hiscore.txt" || (
(Echo Creating and propagating file . . .) 1>CON
Echo %hi%) 1>"hiscore.txt"
I've read a lot of things and I can't find away of doing this that I understand. This might be because I'm a wee newbie though.
What I'm trying to do is:
I have a file called start.txt with the contents
..\dll | toapp.exe "..\posdata\filename.xml" "..\OUT" "..\TEMP"
I want to read the contents of that in a batchfile and take only filename.xml as a variable. From device to device inside the network it changes.
I'm then going to use that variable to copy a file from 1 machine to another but I only want that one file and I can't be sure what it's called without looking in the start.txt. I can do all the copy and checks to make sure it's looking in the correct places but just not the findstr section.
Any idea of what to do to understand would be fantastic
#echo off
set "start_file=start.txt"
for /f tokens^=5^ delims^=\^" %%# in ('type "%start_file%"^|find /i "..\posdata"') do set "xml_file=%%#"
echo %xml_file%
Your question is a little bit unclear.Is this the only line in the file? Is this the exact content? How can I recognize the line with the file?
The script above will work in case there's only one line wwith "..\postdata" string and the content is exact as described in question.
Edit Covering the both cases:
#echo off
setlocal
set "start_file=start.txt"
set "xml_file="
for /f tokens^=5^ delims^=\^" %%# in ('type "%start_file%"^|find /i "..\posdata"^|find /i /v "-storedbpath"') do set "xml_file=%%#"
if not defined xml_file (
for /f "usebackq tokens=9" %%# in ("%start_file%") do (
set "xml_file=%%~#"
)
)
echo %xml_file%
Text this:
for /f "usebackq tokens=4" %%a in ("start.txt") do echo %%~nxa
This question already has answers here:
Example of delayed expansion in batch file
(5 answers)
Variables are not behaving as expected
(1 answer)
Closed 2 years ago.
I just had something completely bizarre come up, and I was wondering if this was expected behavior or if I've found some sort of strange bug in batch file processing. Without going into the details of what I'm trying to do, below is an example script that shows the behavior I'm talking about.
More or less, what I'm experiencing is that global environment variables that are set inside of a function call that is called from inside a if statement don't actually get set until the if statement exits!
#echo off
set myvar=1
echo %myvar% (should be 1)
if [%fakevar%] == [] (
call:setEnvVars
echo %myvar% (should be 2^)
)
echo %myvar% (should be 2)
:setEnvVars
set myvar=2
GOTO:EOF
The output is as follows:
1 (should be 1)
1 (should be 2)
2 (should be 2)
So, to reiterate, is this expected behavior (and why)? Or have I run into some sort of bug?
Your issue have no relation to if command, but to Delayed Expansion. Try this example:
#echo off
set myvar=1
echo %myvar% & set myvar=2 & echo %myvar%
and compare it vs. this one:
#echo off
setlocal EnableDelayedExpansion
set myvar=1
echo %myvar% & set myvar=2 & echo !myvar!
For further details, search for "Delayed Expansion" in this forum and/or read the explanation in set /? command help.
I am looking for a way in a Windows batch file to find if a file contains the word Shutdown a given number of times.
I have tried this using FINDSTR:
FINDSTR /r .*Shutdown.*{5} file.txt
This doesn't seem to work, but if I remove the {5} it executes successfully.
Also I would eventually like the 5 to be a variable, presumably this is possible with some sort of dynamic command?
Thanks
It is possible to use FINDSTR to detect if "Shutdown" appears 5 or more times anywhere within a file. All the information you need is contained within What are the undocumented features and limitations of the Windows FINDSTR command?, but it is more than a bit tricky and not at all obvious.
A regex search can match multiple instances of Shutdown across multiple lines, as long as all intervening characters, including carriage return and linefeed characters, are matched by an appropriate character class range. I cannot post the characters required here, so I will use symbolic notation within angle brackets.
The following regex expression will match any byte character except 0xFF (decimal 255). It consists of a character class expression with two ranges and a gap in the middle for 0xFF. The gap is critical because FINDSTR will fail (and possibly hang) if 0xFF is included:
[<0x01>-<space><tab>-<0xEA>]
You might think the expression should be [<0x01>-<0xFE>], but that does not work because FINDSTR does not collate characters by the numeric code value.
So to look for 5 or more instances of Shutdown anywhere within the file, you would need the following regex search:
Shutdown[<0x01>-<space><tab>-<0xEA>]*Shutdown[<0x01>-<space><tab>-<0xEA>]*Shutdown[<0x01>-<space><tab>-<0xEA>]*Shutdown[<0x01>-<space><tab>-<0xEA>]*Shutdown
The 0xEA (decimal 234) character is an extended ASCII character, and extended ASCII cannot be included on the command line of a FINDSTR search. So the search string must be put in an external file and the /G:file option must be used.
Here is a complete batch script that takes the minimum number of Shutdown instances to search for as the 1st argument, and the name of the file to search as the 2nd argument. Again I use symbolic notation within angle brackets in place of the actual characters needed.
#echo off
set count=%1
set file=%2
setlocal enableDelayedExpansion
set "search="
for /l %%N in (1 1 %count%) do set "search=!search!Shutdown[<0x01>-<space><tab>-<0xEA>]*"
set "search=!search:~0,-9!"
echo(!search!>search.txt
findstr /rg:search.txt %file% >nul&&echo FOUND||echo NOT found
The maximum supported count is limited by the maximum regex string length. For XP the max regex length is 127 bytes, equating to a count of 7. On Vista and Windows 7 the max regex length is 254 bytes, which should support a count of 15. But my testing on Windows 7 only supported a count up to 12. Additional tests reveal the max length is affected by how many string literals and character classes appear, as well as the relative placement of each. But I haven't been able to figure out an exact formula.
If you don't want to use an external file, then the following regex expression is almost as good. It matches any characters except for the following extended ASCII hex codes: 0xE0, 0xE2, 0xE3, 0xE4, 0xE5, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xED, 0xEE, 0xFF.
[<0x01>-<space><tab>-Z]
The full regex search would be:
Shutdown[<0x01>-<space><tab>-Z]*Shutdown[<0x01>-<space><tab>-Z]*Shutdown[<0x01>-<space><tab>-Z]*Shutdown[<0x01>-<space><tab>-Z]*Shutdown
And here is the complete batch script:
#echo off
setlocal enableDelayedExpansion
set count=%1
set file=%2
set "search="
for /l %%N in (1 1 %count%) do set "search=!search!Shutdown[<0x01>-<space><tab>-Z]*"
set "search=!search:~0,-9!"
findstr /rc:"!search!" %file% >nul&&echo FOUND||echo NOT found
.*Shutdown.*Shutdown.*Shutdown.*Shutdown.*Shutdown.*
would seem to be the only way for FINDSTR
srsly.
Test batch:
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%i IN (f5shutdown.txt) DO (
ECHO %%i|FINDSTR /r .*Shutdown.*Shutdown.*Shutdown.*Shutdown.*Shutdown.* >NUL
IF ERRORLEVEL 1 ECHO FAILED IN "%%i"
IF NOT ERRORLEVEL 1 ECHO FOUND IN "%%i"
)
GOTO :eof
Test textfile in f5shutdown.txt
Shutdown
Shutdown Shutdown
Shutdown Shutdown Shutdown Shutdown
Shutdown Shutdown Shutdown Shutdown Shutdown
Shutdown already !Shutdown Shutdown Shutdown Shutdown now
You should now Shutdown Shutdown Shutdown Shutdown Shutdown
ShutdownShutdownShutdownShutdownShutdown
OK, don't shutdown then...
Result:
FAILED IN "Shutdown"
FAILED IN "Shutdown Shutdown"
FAILED IN "Shutdown Shutdown Shutdown Shutdown"
FOUND IN "Shutdown Shutdown Shutdown Shutdown Shutdown"
FOUND IN "Shutdown already !Shutdown Shutdown Shutdown Shutdown now"
FOUND IN "You should now Shutdown Shutdown Shutdown Shutdown Shutdown"
FOUND IN "ShutdownShutdownShutdownShutdownShutdown"
FAILED IN "OK, don't shutdown then..."
Works for me (W7)
Ah - perhaps you meant "occurs on 5 (or whatever) lines or "occurs 5 times in the file"...
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%i IN (f5shutdown.txt) DO (
ECHO %%i|FINDSTR /r .*Shutdown.*Shutdown.*Shutdown.*Shutdown.*Shutdown.* >NUL
IF ERRORLEVEL 1 ECHO FAILED IN "%%i"
IF NOT ERRORLEVEL 1 ECHO FOUND IN "%%i"
)
:: For 'shutdown' on n different lines: (assuming case-insensitive)
FOR /f %%i IN ('FIND /i /c "shutdown" ^<f5shutdown.txt') DO SET shutdowns=%%i
ECHO Second method: %shutdowns% lines found with "Shutdown"
:: For 'shutdown' occurrences (assuming case-insensitive)
SET /a shutdowns=0
FOR /f "delims=" %%i IN (f5shutdown.txt) DO (
SET line=%%i
CALL :findem
)
ECHO Third method found "Shutdown" %shutdowns% times
GOTO :eof
:findem
SET line=%line:"=%
SET after=%line:*shutdown=%
IF NOT DEFINED after SET /a shutdowns+=1&GOTO :EOF
if NOT "%line%"=="%after%" SET "line=%after%"&SET /a shutdowns+=1&GOTO findem
GOTO :eof
(I added an extra non-shutdown-containing line for the test. Found 8 lines and 28 occurrences)
This should detect when shutdown is on only 5 lines in the file.txt
#echo off
for /f %%a in ('find /i /c "shutdown" ^< "file.txt" ') do if %%a EQU 5 echo found it 5 times
This does not relate directly to my development project but I am curious none the less. Recently, after a lot of head-banging, I traced a build problem to an invalid entry in the System PATH variable. On my machine, it contains about 20 entries. I am guessing there has to be an easier way to verify the validity of each entry. Can anyone suggest a way to check this? Thanks for your time.
This code in a batch file (based on this answer) works for me:
#echo off
setlocal DisableDelayedExpansion
set "var=%PATH%"
set "var=%var:"=""%"
set "var=%var:^=^^%"
set "var=%var:&=^&%"
set "var=%var:|=^|%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"
set "var=%var:;=^;^;%"
rem ** This is the key line, the missing quote is intention
set var=%var:""="%
set "var=%var:"=""%"
set "var=%var:;;="";""%"
set "var=%var:^;^;=;%"
set "var=%var:""="%"
set "var=%var:"=""%"
set "var=%var:"";""=";"%"
set "var=%var:"""="%"
setlocal EnableDelayedExpansion
for %%a in ("!var!") do (
endlocal
call :testdir "%%~a"
setlocal EnableDelayedExpansion
)
goto :eof
:testdir
if exist %1 echo OK: %1
if not exist %1 echo NOK: %1
Put the code into a text file, e.g. validatepath.bat.
When run, it should output something like:
OK: C:\Users\abcde
NOK: C:\this\is\no\dir