I am trying to make an impossible loop combination. :) What I need is exclude specific list of services from all services, and all this inside script itself (no external files).
I need somewhat combined several loops and its too complex for me I think. :)
FOR /F "tokens=1* delims=: " %%A IN ('sc query state^= all ^| FIND "SERVICE_NAME:"') DO echo %%B
FOR /F "tokens=2* delims=_" %%S IN ('"FINDSTR /B /I /C:"S_" "%~f0""') DO echo %%S
FOR %%X IN (%%B ^| "FINDSTR /B /I /V /C:"%%S"") DO ???
S_Dhcp
S_WSearch
S_XboxNetApiSvc
In first phase, loop loading services by "SERVICE_NAME:"
Second, loading list of strings (service names) recognition by "S_".
Compare and exclude with output.
There is more easy way which work, but purely out of curiosity, is this possible to make work?
findstr can check for several words, so converting your list to a line of words and use this line with findstr makes things quite easy:
#echo off
setlocal enabledelayedexpansion
REM convert list to line:
for /f "tokens=2* delims=_" %%s IN ('findstr /b "S_" "%~f0"') DO set "exclude=!exclude! %%s"
REM for each service name do:
for /f "tokens=2 delims=: " %%a IN ('sc query state^= all ^|find "SERVICE_NAME:"') do (
REM if it is not in exclude list, echo it:
echo %%a|findstr "%exclude%">nul || echo %%a
)
goto :eof
REM list of services to exclude:
S_Dhcp
S_WSearch
S_XboxNetApiSvc
S_SysMain
S_TabletInputService
S_wuauserv
S_wudfsvc
S_WwanSvc
#echo off
setlocal EnableDelayedExpansion
rem Load the list of names as a string, enclose each name in slahes
rem in order to avoid partial name matches (like NetApi in XboxNetApiSvc)
set "exclude=/"
for %%S in (
Dhcp
WSearch
XboxNetApiSvc
) do set "exclude=!exclude!%%S/"
rem For each active service
FOR /F "tokens=2 delims=: " %%A IN ('sc query state^= all ^|find "SERVICE_NAME:"') do (
rem If the name is not in the exclude list, echo it:
IF "!exclude:/%%A/=!" EQU "%exclude%" echo %%A
)
Related
Say I have a search mask like "*casting?00*" that should corresponds to a directory in a tree, by the amount of filename matches. How do I return only the subdirectory with most filename matches?
Loop recursively over the subfolders, count the matching files in each (save them to a temporary file for further processing). Sort it and get the last line, separating counter and foldername:
#echo off
setlocal enabledelayedexpansion
del tmp.csv 2>nul
for /r /d %%a in (*) do (
set "count="
for /f %%b in ('dir /b "%%a\*casting?00*" 2^>nul ^|find /c /v ""') do (
set "count= %%b"
echo !count:~-4!,%%a >>tmp.csv
)
)
sort tmp.csv
for /f "tokens=1,* delims=, " %%a in ('sort tmp.csv') do set "folder=%%b" & set "count=%%a"
echo --- %count% findings in %folder% ---
Note: If more than one folder have the same max. amount of matching files, this will give you the last one only.
Edit to use an array instead of a file (less readable in my opinion, but just to show, how it can be done):
#echo off
setlocal enabledelayedexpansion
set index=0
for /r /d %%a in (*) do (
set "count="
set /a index+=1
for /f %%b in ('dir /b "%%a\*casting?00*" 2^>nul ^|find /c /v ""') do (
set "count= %%b"
set "Array[!index!]=!count:~-4!,%%a
)
)
set Array
for /f "tokens=1,* delims=, " %%x in (
'(for /f "tokens=2 delims==" %%a in ('set Array'^) do #echo %%a^)^|sort'
) do set "count=%%x" & set "folder=%%y"
echo --- %count% findings in %folder% ---
I somewhat apologize as I've hijacked this question a bit. This isn't meant to be a competing answer -- rather a continuation of the discussion using an array of variables.
I should probably use the term "pseudo-array" for my approach. I would replace the traditional incremental array index with the count of files. I would add the foldername to the variable name to eliminate duplicates.
There are plenty of "gotcha's". Which is pretty much always true in CMD. Special characters will cause problems. With the method I will show, the characters ", =, ], and [ will definitely cause problems. Another issue is the length of the command line and variable name length. If your paths get to be really long then this code will choke. I think it's somewhere around 8,000.
Generally, to get numbers to sort alphabetically, you must pad them with leading characters (commonly zeros or spaces). When numbers will be arbitrary and incremental, my personal preference is to start with a large number like 10000 instead of 0 or 1. In this scenario, though, I am not using incremental numbers but instead am using the count of files as a pseudo-index. I prefer math to padding zeros, so I just add 1,000,000 to the count. This will keep it alphabetical as long as there are 8,999,999 files or fewer in any subfolder. I'm pretty sure the maximum possibility within CMD math limitations would be starting with 1,000,000,000 which allows for around 1,147,483,648 files.
#echo off
setlocal enabledelayedexpansion
:: Just in case there are any array variables already defined
:: we'll clear them first.
for /f "delims==" %%a in ('set a1 2^>nul') do set %%a=
for /f "delims==" %%a in ('set a2 2^>nul') do set %%a=
for /r /d %%a in (*) do (
for /f %%b in ('dir /b "%%a\*casting?00*" 2^>nul ^|find /c /v ""') do (
set /a filecount=%%b + 1000000
set "a1[!filecount!]%%~pnxa=%%b"
set "a2[%%~a]=%%b"
)
)
:: Things you can do with this . . .
:: Basic list in order from largest count to smallest
set a1|sort /r
:: List the "first" folder with the most files
echo.
echo The "first" folder with the most files:
for /f "tokens=2 delims==]" %%a in ('set a1 ^| sort /r') do echo %%a & goto :continue
:continue
:: The largest file count
echo.
for /f "tokens=2 delims=[]" %%a in ('set a1 ^| sort /r') do (
set /a maxfiles = %%a - 1000000
echo The most files in any subfolder is !maxfiles!.
goto :continue
)
:continue
:: All of the subfolders that share the max number of files:
echo.
echo.
echo.
for /f "tokens=2 delims=[]=" %%a in ('set a1 ^| sort /r') do (
set /a maxfiles = %%a - 1000000
echo All the subfolders with the maximum of !maxfiles! files . . .
for /f "tokens=2 delims==]" %%b in ('set a1[%%a]') do echo. %%b
goto :continue
)
:continue
:: The subfolders with 0 files
echo.
echo.
echo.
echo The subfolders with 0 files . . .
for /f "tokens=2 delims==]" %%a in ('set a1[1000000] 2^>nul') do (
set nonempty=yes
echo. %%a
)
if not defined nonempty echo. There are none.
:: CSV style output
echo.
echo.
echo.
for /f "tokens=2,3 delims=]=" %%a in ('set a1 ^| sort /r') do echo "%%a",%%b
The a2 array is not used here but just an example of a matching array arranged differently.
I need to set a variable to a substring I get from a find command, but it is returning the command
findstr /is "CouId:" C:\dev\AssayInfo.txt
set number=findstr /is "CouId:" C:\dev\AssayInfo.txt
echo %number%
pause
This is what the file that I'm using findstr looks like:
Protocol: NVD_RCP_Fluidic_Accuracy_v0.4
ProtocolVersion: 1
SampleId: FLQC+20191126+00111280+96
InstrumentId: 123456789001
CouId: 138527011
CouSlot: 1
The variable should have the value 138527011 in this case.
Here you go:
#echo off
for /f "tokens=1,* delims=: " %%i in ('type "C:\dev\AssayInfo.txt" ^| findstr /i CouID') do set "number=%%j"
echo %number%
:# Here you can add your if statements etc.
pause
Note, that this is exactly what you required, as per this question and not the other question and therefore this is all I can give you now.
However, this is not even needed, you can do it without the set variable:
#echo off
for /f "tokens=1,* delims=: " %%i in ('type "C:\dev\AssayInfo.txt" ^| findstr /i CouID') do (
echo %%i
:# Here you can add your if statements etc.
)
pause
Personally, I would use:
#echo off
for /F "tokens=2" %%A IN ('findstr /ibc:"CouId: " C:\dev\AssayInfo.txt') do set "num=%%A"
rem Do some code here:
pause
exit /b 0
which is much shorter.
Note that direct comparisons can be done directly inside the for loop like:
#echo off
setlocal EnableDelayedExpansion
for /F "tokens=2" %%A IN ('findstr /ibc:"CouId: " C:\dev\AssayInfo.txt') do (
set "num=%%A"
rem Do sum comparisons with '!num!', not '%num%'!:
)
pause
exit /b %errorlevel%
I have multiple files such as qulogscan_141201.txt (year month day)
am trying to create a batch which will pick that file and find "notloaded" inside it, what I have done so far is this:
Echo NOTLOADED
Echo\
set yy=%date:~-2%
set mm=%date:~-7,2%
set dd=%date:~-10,2%
setlocal EnableDelayedExpansion
rem Assemble the list of line numbers
set numbers=
set "folder=J:\Console\Output_Del\sscmex\qulogscan_%yy%%mm%%dd%.txt"
for /F "delims=:" %%a in ('findstr /I /N /C:"NOTLOADED" "%folder%"') do (
set /A after=%%a+3
set "numbers=!numbers!!after!: "
)
rem Search for the lines
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%folder%" ^| findstr /B "%numbers%"') do echo %%b)
how can I do to make it select the file qulogscan_.txt ignoring the datastamps without renaming it ?
I'm using the following code to get a list of programs being run at start up, and log them to a file.
for /f "skip=2 tokens=1,2*" %%A in ('REG QUERY "HKCU\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run" 2^>NUL') do echo %%A : %%C >> Log.txt
This works with entries where the value name doesn't contain a space, but when it does, such as with "Google Update", it messes up the tokens, and %%C becomes: REG_SZ <path>, instead of just the path.
Does anyone have a better way to query the registry and log its values?
Well I got one working solution, I'd still love to see if anyone has anything better.
for /f "skip=2 tokens=*" %%A in ('REG QUERY "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" 2^>NUL') do (
set regstr=%%A
set regstr=!regstr: =^|!
for /f "tokens=1,3 delims= |" %%X in ("!regstr!") do (
echo %%X : %%Y
)
)
Version specific, works in XP, does not work in Win 7 - see comments for details.
Columns in the output are separated by tab char (0x09), so use only tab as a separator:
for /f "skip=2 tokens=1,2* delims= " %%A
This does not show well because of how markup handles white chars, but the character after delims= must be actual TAB
Here's a better way via WMI calling the Win32_StartupCommand class, results output to screen as well as a CSV file in the same folder as per script name:
#echo off
setlocal enabledelayedexpansion
cd \ & pushd "%~dp0"
if exist "%~n0.tmp" (del /f /q "%~n0.tmp")
if exist "%~n0.csv" (del /f /q "%~n0.csv")
wmic /namespace:\\root\cimv2 path Win32_StartupCommand get /all /format:csv >"%~n0.tmp"
for /f "tokens=1,2,3,4,5,6,7,8,9 usebackq delims=, skip=2" %%a in (`type "%~n0.tmp"`) do (
echo %%b, %%c >>"%~n0.csv"
echo %%b, %%c
)
if exist "%~n0.tmp" (del /f /q "%~n0.tmp")
popd & endlocal
exit /b 0`
I'm trying to concatenate many files into two individual files.
The first file will be a concatenation of all other files with "bob" in the filename. The second file will be a concatenation of all files WITHOUT "bob" in the filename. Both files will output the name of the file before actually doing the concatenation.
Here's what I have so far:
#echo off
setlocal EnableDelayedExpansion
set bob=All_bob.txt
set jimmy=All_jimmy.txt
if exist %bob% del %bob%
if exist %jimmy% del %jimmy%
for %%a in (*bob*.txt) do (
echo /* >>%bob%
echo * %%a >>%bob%
echo */ >>%bob%
copy/b %bob%+"%%a" %bob%
echo. >>%bob%
echo. >>%bob%)
for %%a not in (*bob*.txt) do (
echo /* >>%jimmy%
echo * %%a >>%jimmy%
echo */ >>%jimmy%
copy/b %jimmy%+"%%a" %jimmy%
echo. >>%jimmy%
echo. >>%jimmy%)
However, the second FOR loop (at the bottom) doesn't want to play nice using "not", and using an exclamation point like this...
for %%a !(*bob*.txt) do (
...doesn't want to work, either. So how do I concatenate files that do NOT contain what is inside the parenthesis?
I don't think there is a clean solution to this.
You could probably use FINDSTR to filter %%a but that would require turning *bob*.txt into a regular expression and that is probably not easy to automate.
Another (ugly) solution is to use nested loops:
echo bob:
for %%a in (*bob*.txt) do (
echo %%a
)
echo not bob:
for %%a in (*) do (
setlocal ENABLEDELAYEDEXPANSION&set inc=1
for %%b in (*bob*.txt) do if "%%~a"=="%%~b" set inc=0
if "!inc!"=="1" echo %%a
endlocal
)
How about using find:
for /F %%a in ('dir /b *.txt') do (
echo %%a | find /V "bob")
This should return all .txt files that don't have "bob" in them.
Using findstr and a regular expression for *bob*.txt:
for /f "usebackq delims=" %%a in (`dir /b ^| findstr ".*bob.*\.txt"`) do (…)
Just use the /V switch to process all other files:
for /f "usebackq delims=" %%a in (`dir /b ^| findstr /v ".*bob.*\.txt"`) do (…)
You can use the help command or the /? switch for for or findstr for more information.
I cleared the delimiters (delims=) to allow for spaces in the filenames.