Running a cmd .bat file with loops and conditions - windows

Hi I am trying to run a scrapy spider using start command from a cmd batch file. I want to run the spider parallely for 10 names from a csv file which contains more than 500 names. So my thought is to basically add some conditions in the loop from 1 to 500 that checks if the 10 command windows have closed, if not then wait for them to close (they auto close after spider is finished). Once the 10 windows which had opened, are closed, open the next 10 and so on. Following is the code I have, i am pretty sure it has big syntax errors. Could you help me debug? Thanks
cd /d "C:\Users\xyz"
for /f "tokens=1,*" %%m in ('tasklist ^| find /I /C "conhost.exe"') do (set var1=%%m)
set counter=1
for /f "usebackq tokens=1 delims=," %%n in ("test.csv") do (
(START /MIN "" scrapy crawl xyz_scraper -a query="%%n" -a pages=20)
set /a counter=counter+1
for /f "tokens=1,*" %%p in ('tasklist ^| find /I /C "conhost.exe"') do (set var2=%%p)
SET /A _result=counter%%10
echo %_result%
IF _result EQU 0 (
:abcd
timeout /t 10
if var2 EQU var1 (
goto bcde
)
ELSE (
goto abcd)
)
:bcde
)
pause
EDIT: deleted the for loop one. Edited the above code based on some suggestions. I don't understand where would i use quotes for variables and where not and how to print a variables value to cmd.
The updated code below:
cd /d "C:\Users\sodhian\sodhi-scraper"
for /f "tokens=1,*" %%m in ('tasklist ^| find /I /C "conhost.exe"') do (set var1=%%m)
echo %var1%
set counter=1
for /f "usebackq tokens=1 delims=," %%n in ("test comp.csv") do (
(START /MIN "" scrapy crawl ind_scraper -a query="%%n" -a pages=20)
set /a "counter=counter+1"
echo %counter%
SET /A _result="counter%%2"
echo %_result%
IF "%_result%" EQU "0" (
:abcd
timeout /t 10
for /f "tokens=1,*" %%p in ('tasklist ^| find /I /C "conhost.exe"') do (set var2=%%p)
echo %var2%
if var2==var1 (
goto bcde
)
ELSE (
goto abcd)
)
:bcde
)
pause
Edit 2:
Based on Stephan's answer. Tried to accomplish what i mentioned in comment of the answer:
setlocal enabledelayedexpansion
set counter=0
for /f "usebackq tokens=1 delims=," %%n in ("test comp.csv") do (
set /a counter+=1
start /MIN "MySpider!counter!" scrapy crawl ind_scraper -a query="%%n" -a pages=20
for /f "tokens=1,*" %%b in ('tasklist /v ^| find /I /C "MySpider"') do (set var1=%%b)
if !var1! geq 5 call :wait
)
:wait
timeout /t 5
for /f "tokens=1,*" %%p in ('tasklist /v ^| find /I /C "MySpider"') do (set var2=%%p)
if !var2! geq 5 call :wait
goto :eof
Changed it to the following: (the /v (verbose option in tasklist was making the above slow)
setlocal enabledelayedexpansion
set counter=0
set max_scrappers=7
for /f "tokens=1,*" %%a in ('tasklist ^| find /C "conhost"') do (set var1=%%a)
for /f "usebackq tokens=1 delims=," %%n in ("test comp.csv") do (
set /a counter+=1
start /min "MySpider!counter!" scrapy crawl ind_scraper -a query="%%n" -a pages=20
for /f "tokens=1,*" %%b in ('tasklist ^| find /C "conhost"') do (set var2=%%b)
set /a var3=!var2!-!var1!
if !var3! geq !max_scrappers! call :wait
)
:wait
for /f "tokens=1,*" %%p in ('tasklist ^| find /C "conhost"') do (set var4=%%p)
set /a var5=!var4!-!var1!
if !var5! geq !max_scrappers! call :wait
goto :eof

As already noted in the comments, labels inside a code block don't work. But you can call a "function", where goto and labels are no problem:
I choosed other numbers and another command to make it work on every system (and faster). Replacing the timeout command with your spider and adapting the numbers should be no problem.
#echo off
setlocal enabledelayedexpansion
REM next line just for generating a testfile:
>"test comp.csv" (for /l %%i in (1,1,10) do echo !random:~-1!)
set counter=0
for /f "usebackq tokens=1 delims=," %%n in ("test comp.csv") do (
set /a counter+=1
start "MySpider!counter!" timeout %%n
if !counter! geq 3 call :wait
)
:wait
tasklist /v|find "MySpider">nul && goto :wait
set counter=0
goto :eof
Searching for conhost is not a good idea, because there could be other processes. Choose an unique window title instead (MySpider in my example) and look for that title (tasklist /v)

Related

Filter results in batch script for user printer selection

I am trying to create a script to allow users to temporarily set the default windows printer to a selected printer (PDF, XPS, OneNote) before printing and then automatically set the default back to the original printer after a specified time.
I have managed to incorporate elements of many different examples to get to the stage where the script is functioning, although it is creating an extra entry at the start and end of the list.
I would like to filter the list of printers the user is shown to just ones from the appropriate list (e.g. PDF, XPS, OneNote).
Any help would be greatly appreciated.
#echo off
setlocal enableDelayedExpansion
FOR /F "tokens=2* delims==" %%A in (
'wmic printer where "default=True" get name /value'
) do SET DefaultPrinter=%%A
ECHO.
ECHO ==============================================================
ECHO Current Default Printer
ECHO ==============================================================
ECHO.
ECHO Default Printer = %DefaultPrinter%
ECHO.
pause
Cls
ECHO ==============================================================
ECHO Processing locally installed printers
ECHO ==============================================================
::build "array" of printers
set printerCnt=0
for /f "eol=: delims=" %%F in ('wmic printer get Name') do (
set /a printerCnt+=1
set "printer!printerCnt!=%%F"
)
::print menu
for /l %%N in (1 1 %printerCnt%) do echo %%N - !printer%%N!
echo(
:get selection
set selection=
set /p "selection=Enter a printer number: "
echo You picked !printer%selection%!
set NewPrinter=!printer%selection%!
::trim selection
set str=%NewPrinter%
for /l %%a in (1,1,31) do if "!str:~-1!"==" " set str=!str:~0,-1!
RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n "%str%"
TIMEOUT 10
RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n "%DefaultPrinter%"
[Edit /]
I have included the code I ended up using. This was based on the answer provided by #Hackoo and I incorporated elements provided by #Magoo also. There is probably a more elegant way to write this code but I am new to this so laid it out as I understood it.
#echo off
Mode 70,30 & color F0
Title Healthmail Printer Selection
FOR /F "tokens=2* delims==" %%A in (
'wmic printer where "default=True" get name /value'
) do SET "DefaultPrinter=%%A"
ECHO.
ECHO ==============================================================
ECHO Current Default Printer
ECHO ==============================================================
ECHO.
ECHO Default Printer = [%DefaultPrinter%]
ECHO.
TIMEOUT /T 2 /NoBreak>nul
Cls
ECHO.
ECHO ==============================================================
ECHO Available Printers
ECHO ==============================================================
Setlocal EnableDelayedExpansion
::build "array" of printers
Set "FilterList=%Temp%\FilterList.txt"
REM Create a file to filter just for PDF printers
>"%FilterList%" (
echo PDF
)
set printerCnt=0
#for /f "delims=" %%a in (
'wmic printer get Name ^|findstr /G:%FilterList%"'
) do (
#for /f "delims=" %%b in ("%%a") do (
set /a printerCnt+=1
set "printer!printerCnt!=%%~nb"
)
)
::If no printers have been found, go to filterlistlong
:zerofilterprinters
IF !printerCnt!==0 GOTO :filterlistlong
IF !printerCnt! gtr 0 GOTO :printmenu
:filterlistlong
Set "FilterListLong=%Temp%\FilterListLong.txt"
REM Create a file to filter with each word like XPS,OneNote and PDF
>"%FilterListLong%" (
echo PDF
echo XPS
echo OneNote
)
set printerCnt=0
#for /f "delims=" %%a in (
'wmic printer get Name ^|findstr /G:%FilterListLong%"'
) do (
#for /f "delims=" %%b in ("%%a") do (
set /a printerCnt+=1
set "printer!printerCnt!=%%~nb"
)
)
:printmenu
SET "choices="
for /l %%N in (1 1 %printerCnt%) do SET "choices=!choices!%%N"&SET "printer%%N=!printer%%N!"&IF %printercnt% gtr 1 echo %%N - !printer%%N!
echo(
:get selection
:: If no available options, exit
IF NOT DEFINED choices GOTO :EOF
:: If only 1 option, auto-select that
IF %choices%==1 SET /a selection=1&GOTO autoselect
choice /c %choices% /m "Enter a printer number: "
set selection=%ERRORLEVEL%
:: Error condition
IF %selection% gtr %printercnt% GOTO :EOF
:: Control-C
IF %selection% equ 0 GOTO :EOF
cls
ECHO ==============================================================
ECHO You selected: !printer%selection%!
ECHO ==============================================================
echo.
echo. Please proceed to print document.
echo.
echo. This window will close automatically in 30 seconds.
::GOTO :setprinter
:autoselect
set NewPrinter=!printer%selection%!
cls
ECHO ==============================================================
ECHO Printer selected: !printer%selection%!
ECHO ==============================================================
echo.
echo. Please proceed to print document.
echo.
echo. This window will close automatically in 10 seconds.
:setprinter
RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n "%NewPrinter%"
TIMEOUT /T 10 /nobreak > NUL
RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n "%DefaultPrinter%"
GOTO :EOF
If Exist "%FilterList%" Del "%FilterList%"
If Exist "%FilterListLong%" Del "%FilterListLong%"
The output of WMIC is unicode !
The trailing <CR> can be removed by passing the value through another FOR /F loop.
This also removes the phantom "blank" line (actually a <CR>) and in this case you don't need to use the Trim function !
#echo off
Mode 70,30 & color 0A
Title Filter results in batch script for user printer selection
FOR /F "tokens=2* delims==" %%A in (
'wmic printer where "default=True" get name /value'
) do SET "DefaultPrinter=%%A"
ECHO.
ECHO ==============================================================
ECHO Current Default Printer
ECHO ==============================================================
ECHO.
ECHO Default Printer = [%DefaultPrinter%]
ECHO.
TIMEOUT /T 3 /NoBreak>nul
Cls
ECHO.
ECHO ==============================================================
ECHO Processing locally installed printers
ECHO ==============================================================
Setlocal EnableDelayedExpansion
::build "array" of printers
REM We Ignore printer begin with Micro or Fax in the name
Set "FilterList=%Temp%\FilterList.txt"
REM We create a file to filter with each word like XPS,OneNote and PDF
>"%FilterList%" (
echo XPS
echo OneNote
echo PDF
)
set printerCnt=0
#for /f "skip=1 delims=" %%a in (
'wmic printer get Name ^|findstr /G:%FilterList%"'
) do (
#for /f "delims=" %%b in ("%%a") do (
set /a printerCnt+=1
set "printer!printerCnt!=%%~nb"
)
)
::print menu
for /l %%N in (1 1 %printerCnt%) do echo [%%N] - [!printer%%N!]
echo ==============================================================
:get selection
set selection=
set /p "selection=Enter a printer number: "
set "NewPrinter=!printer%selection%!"
echo. You picked [%NewPrinter%]
RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n "%NewPrinter%"
TIMEOUT /T 10
RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n "%DefaultPrinter%"
If Exist "%FilterList%" Del "%FilterList%"
#echo off
setlocal ENABLEDELAYEDEXPANSION
SET "printfilter=%1"
FOR /F "tokens=2* delims==" %%A in (
'wmic printer where "default=True" get name /value'
) do SET DefaultPrinter=%%A
ECHO.
ECHO ==============================================================
ECHO Current Default Printer
ECHO ==============================================================
ECHO.
ECHO Default Printer = %DefaultPrinter%
ECHO.
pause
Cls
ECHO ==============================================================
ECHO Processing locally installed printers
ECHO ==============================================================
::build "array" of printers
set printerCnt=0
for /f "skip=1eol=: delims=" %%F in ('wmic printer get Name') do (
set /a printerCnt+=1
set "printer!printerCnt!=%%F"
IF DEFINED printfilter ECHO %%F|FIND /i "%printfilter%" >nul&IF ERRORLEVEL 1 SET /a printercnt-=1
)
iF NOT DEFINED printfilter (
set "printer%printerCnt%="
SET /a printercnt-=1
)
::print menu
SET "choices="
for /l %%N in (1 1 %printerCnt%) do SET "choices=!choices!%%N"&SET "printer%%N=!printer%%N:~0,-1!"&IF %printercnt% gtr 1 echo %%N - !printer%%N!
echo(
:get selection
:: If no available options, exit
IF NOT DEFINED choices GOTO :EOF
:: If only 1 option, auto-select that
IF %choices%==1 SET /a selection=1&GOTO autoselect
choice /c %choices% /m "Enter a printer number: "
set selection=%ERRORLEVEL%
:: Error condition
IF %selection% gtr %printercnt% GOTO :EOF
:: Control-C
IF %selection% equ 0 GOTO :EOF
echo You picked !printer%selection%!
:autoselect
set NewPrinter=!printer%selection%!
::trim selection
set str=%NewPrinter%
for /l %%a in (1,1,31) do if "!str:~-1!"==" " set str=!str:~0,-1!
ECHO RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n "%str%"
ECHO TIMEOUT 10
ECHO RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n "%DefaultPrinter%"
GOTO :EOF
Amusing...
First, to specify the filter, simply append an appropriate string (PDF, XPS, OneNote) to the batchname as a parameter. Omitting this selects ALL.
First step is to add the skip=1 to the for /f ... %%F... so that the Name line from the report is skipped.
Next, if the filter is invoked, detect whether the printername includes the filter string. If it does NOT, then back up the printer-counter.
Having built the array, noting that the last (bogus) entry will have been recorded UNLESS the filter is invoked, clear the last (bogus) entry and back up the counter.
The point with WMIC output is that it's not only Unicode, but it has a line-terminator of <CR><CR><LF> instead of <CR><LF>. The text values stored in the array each have a terminal <CR>. Hence the bogus last entry.
So, for each entry passing the filter, build a string of the options allowed into choices, and remove the last character from the printer name string and show it.
Now if there are no choices, exit (or something else).
If there's only one choice, auto-select it (and don't show the selection-list) Otherwise use choice to select the printers from the list.
You'd need to add to the list of choices to allow selection of printers beyond #9.
and I chose to simply echo the rundll32s and timeout for testing.
I'd just enumerate the printers once, and get rid of much of the unnecessary screen output:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "SysDir=%SystemRoot%\System32"
For /F "Delims==" %%G In ('"(Set Printer[) 2>NUL"') Do Set "%%G="
Set "DefaultPrinter="
For /F "Tokens=1-3,* Delims=[,]" %%G In ('%SysDir%\wbem\WMIC.exe Printer Get
Default^, Name /Format:CSV 2^>NUL ^| %SysDir%\findstr.exe "E\>" ^|
%SysDir%\find.exe /V /N ""') Do For /F "Tokens=*" %%K In ("%%J") Do (
Echo([%%G] %%K
If "%%I" == "TRUE" Set "DefaultPrinter=%%K"
Set "Printer[%%G]=%%K")
If Not Defined Printer[1] (Echo No printers found.
Echo Press any key to end . . .
GoTo :EOF)
Echo(
(Set DefaultPrinter) 2>NUL || Echo No default printer found.
:Selection
Echo(
Set "UserPrinter="
Set /P "UserPrinter=Enter the number for your preferred printer>"
Set "UserPrinter=%UserPrinter:"=%"
Set Printer[ | %SysDir%\findstr.exe /B /L "Printer[%UserPrinter%]=" 1>NUL || (
GoTo Selection)
SetLocal EnableDelayedExpansion
For %%G In ("!Printer[%UserPrinter%]!") Do EndLocal & Set "UserPrinter=%%~G"
Echo(
Echo You Selected %UserPrinter%
%SysDir%\timeout.exe /T 3 /NoBreak 1>NUL
%SysDir%\rundll32.exe %SysDir%\printui.dll,PrintUIEntry /y /n "%UserPrinter%"
%SysDir%\timeout.exe /T 10
%SysDir%\rundll32.exe %SysDir%\printui.dll,PrintUIEntry /y /n "%DefaultPrinter%"
[EDIT /]
If you really do need to support windows-7, and windows-server-2008-r2, and you cannot guarantee that the XSL files have been copied up a level on the target machine, then it should still possible. Although it looks like a lot of extra lines, the following example should not seriously impact your script speed, other than the extra call to the relatively slow WMIC.exe, (your example, as well as the other currently submitted answers, already use more than one WMIC command).
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "SysDir=%SystemRoot%\System32"
%SysDir%\wbem\WMIC.exe OS Where "Version Like '6.1%%'" Get Version 2>NUL ^
| %SysDir%\find.exe "6.1" 1>NUL && Call :GetXSLDir
For /F "Delims==" %%G In ('"(Set Printer[) 2>NUL"') Do Set "%%G="
Set "DefaultPrinter="
For /F "Tokens=1-3,* Delims=[,]" %%G In ('%SysDir%\wbem\WMIC.exe Printer Get
Default^, Name /Format:"%XSLDir%csv.xsl" 2^>NUL ^| %SysDir%\findstr.exe "E\>"
^| %SysDir%\find.exe /V /N ""') Do For /F "Tokens=*" %%K In ("%%J") Do (
Echo([%%G] %%K
If "%%I" == "TRUE" Set "DefaultPrinter=%%K"
Set "Printer[%%G]=%%K")
If Not Defined Printer[1] (Echo No printers found.
Echo Press any key to end . . .
GoTo :EOF)
Echo(
(Set DefaultPrinter) 2>NUL || Echo No default printer found.
:Selection
Echo(
Set "UserPrinter="
Set /P "UserPrinter=Enter the number for your preferred printer>"
Set "UserPrinter=%UserPrinter:"=%"
Set Printer[ | %SysDir%\findstr.exe /B /L "Printer[%UserPrinter%]=" 1>NUL || (
GoTo Selection)
SetLocal EnableDelayedExpansion
For %%G In ("!Printer[%UserPrinter%]!") Do EndLocal & Set "UserPrinter=%%~G"
Echo(
Echo You Selected %UserPrinter%
%SysDir%\timeout.exe /T 3 /NoBreak 1>NUL
%SysDir%\rundll32.exe %SysDir%\printui.dll,PrintUIEntry /y /n "%UserPrinter%"
%SysDir%\timeout.exe /T 10
%SysDir%\rundll32.exe %SysDir%\printui.dll,PrintUIEntry /y /n "%DefaultPrinter%"
GoTo :EOF
:GetXSLDir
For %%G In (Default InstallLanguage XSLDir) Do Set "%%G="
For /F "Tokens=1,2*" %%G In ('%SysDir%\reg.exe Query
HKLM\System\CurrentControlSet\Control\Nls\Language 2^>NUL ^|
%SysDir%\findstr.exe /I "\<Default\> \<InstallLanguage\>"'
) Do For /F "Tokens=2 Delims=:" %%J In ('%SysDir%\findstr.exe "::%%I:" "%~f0"'
) Do Set "%%G=%%J"
If Exist "%SysDir%\wbem\%Default%\*.xsl" (Set "XSLDir=%SysDir%\wbem\%Default%\"
) Else If Exist "%SysDir%\wbem\%InstallLanguage%\*.xsl" (
Set "XSLDir=%SysDir%\wbem\%InstallLanguage%\")
For %%G In (Default InstallLanguage) Do Set "%%G="
Exit /B
::0001:ar
::0002:bg
::0003:ca
::0004:zh-Hans
::0005:cs
::0006:da
::0007:de
::0008:el
::0009:en
::000A:es
::000B:fi
::000C:fr
::000D:he
::000E:hu
::000F:is
::0010:it
::0011:ja
::0012:ko
::0013:nl
::0014:no
::0015:pl
::0016:pt
::0017:rm
::0018:ro
::0019:ru
::001A:hr
::001B:sk
::001C:sq
::001D:sv
::001E:th
::001F:tr
::0020:ur
::0021:id
::0022:uk
::0023:be
::0024:sl
::0025:et
::0026:lv
::0027:lt
::0028:tg
::0029:fa
::002A:vi
::002B:hy
::002C:az
::002D:eu
::002E:hsb
::002F:mk
::0030:st
::0031:ts
::0032:tn
::0033:ve
::0034:xh
::0035:zu
::0036:af
::0037:ka
::0038:fo
::0039:hi
::003A:mt
::003B:se
::003C:ga
::003D:yi
::003E:ms
::003F:kk
::0040:ky
::0041:sw
::0042:tk
::0043:uz
::0044:tt
::0045:bn
::0046:pa
::0047:gu
::0048:or
::0049:ta
::004A:te
::004B:kn
::004C:ml
::004D:as
::004E:mr
::004F:sa
::0050:mn
::0051:bo
::0052:cy
::0053:km
::0054:lo
::0055:my
::0056:gl
::0057:kok
::0058:mni
::0059:sd
::005A:syr
::005B:si
::005C:chr
::005D:iu
::005E:am
::005F:tzm
::0060:ks
::0061:ne
::0062:fy
::0063:ps
::0064:fil
::0065:dv
::0066:bin
::0067:ff
::0068:ha
::0069:ibb
::006A:yo
::006B:quz
::006C:nso
::006D:ba
::006E:lb
::006F:kl
::0070:ig
::0071:kr
::0072:om
::0073:ti
::0074:gn
::0075:haw
::0076:la
::0077:so
::0078:ii
::0079:pap
::007A:arn
::007C:moh
::007E:br
::0080:ug
::0081:mi
::0082:oc
::0083:co
::0084:gsw
::0085:sah
::0086:qut
::0087:rw
::0088:wo
::008C:prs
::0091:gd
::0092:ku
::0093:quc
::0401:ar-SA
::0402:bg-BG
::0403:ca-ES
::0404:zh-TW
::0405:cs-CZ
::0406:da-DK
::0407:de-DE
::0408:el-GR
::0409:en-US
::040A:es-ES_tradnl
::040B:fi-FI
::040C:fr-FR
::040D:he-IL
::040E:hu-HU
::040F:is-IS
::0410:it-IT
::0411:ja-JP
::0412:ko-KR
::0413:nl-NL
::0414:nb-NO
::0415:pl-PL
::0416:pt-BR
::0417:rm-CH
::0418:ro-RO
::0419:ru-RU
::041A:hr-HR
::041B:sk-SK
::041C:sq-AL
::041D:sv-SE
::041E:th-TH
::041F:tr-TR
::0420:ur-PK
::0421:id-ID
::0422:uk-UA
::0423:be-BY
::0424:sl-SI
::0425:et-EE
::0426:lv-LV
::0427:lt-LT
::0428:tg-Cyrl-TJ
::0429:fa-IR
::042A:vi-VN
::042B:hy-AM
::042C:az-Latn-AZ
::042D:eu-ES
::042E:hsb-DE
::042F:mk-MK
::0430:st-ZA
::0431:ts-ZA
::0432:tn-ZA
::0433:ve-ZA
::0434:xh-ZA
::0435:zu-ZA
::0436:af-ZA
::0437:ka-GE
::0438:fo-FO
::0439:hi-IN
::043A:mt-MT
::043B:se-NO
::043D:yi-Hebr
::043E:ms-MY
::043F:kk-KZ
::0440:ky-KG
::0441:sw-KE
::0442:tk-TM
::0443:uz-Latn-UZ
::0444:tt-RU
::0445:bn-IN
::0446:pa-IN
::0447:gu-IN
::0448:or-IN
::0449:ta-IN
::044A:te-IN
::044B:kn-IN
::044C:ml-IN
::044D:as-IN
::044E:mr-IN
::044F:sa-IN
::0450:mn-MN
::0451:bo-CN
::0452:cy-GB
::0453:km-KH
::0454:lo-LA
::0455:my-MM
::0456:gl-ES
::0457:kok-IN
::0458:mni-IN
::0459:sd-Deva-IN
::045A:syr-SY
::045B:si-LK
::045C:chr-Cher-US
::045D:iu-Cans-CA
::045E:am-ET
::045F:tzm-Arab-MA
::0460:ks-Arab
::0461:ne-NP
::0462:fy-NL
::0463:ps-AF
::0464:fil-PH
::0465:dv-MV
::0466:bin-NG
::0467:fuv-NG
::0468:ha-Latn-NG
::0469:ibb-NG
::046A:yo-NG
::046B:quz-BO
::046C:nso-ZA
::046D:ba-RU
::046E:lb-LU
::046F:kl-GL
::0470:ig-NG
::0471:kr-NG
::0472:om-ET
::0473:ti-ET
::0474:gn-PY
::0475:haw-US
::0476:la-Latn
::0477:so-SO
::0478:ii-CN
::0479:pap-029
::047A:arn-CL
::047C:moh-CA
::047E:br-FR
::0480:ug-CN
::0481:mi-NZ
::0482:oc-FR
::0483:co-FR
::0484:gsw-FR
::0485:sah-RU
::0486:qut-GT
::0487:rw-RW
::0488:wo-SN
::048C:prs-AF
::048D:plt-MG
::048E:zh-yue-HK
::048F:tdd-Tale-CN
::0490:khb-Talu-CN
::0491:gd-GB
::0492:ku-Arab-IQ
::0493:quc-CO
::0501:qps-ploc
::05FE:qps-ploca
::0801:ar-IQ
::0803:ca-ES-valencia
::0804:zh-CN
::0807:de-CH
::0809:en-GB
::080A:es-MX
::080C:fr-BE
::0810:it-CH
::0811:ja-Ploc-JP
::0813:nl-BE
::0814:nn-NO
::0816:pt-PT
::0818:ro-MD
::0819:ru-MD
::081A:sr-Latn-CS
::081D:sv-FI
::0820:ur-IN
::082C:az-Cyrl-AZ
::082E:dsb-DE
::0832:tn-BW
::083B:se-SE
::083C:ga-IE
::083E:ms-BN
::083F:kk-Latn-KZ
::0843:uz-Cyrl-UZ
::0845:bn-BD
::0846:pa-Arab-PK
::0849:ta-LK
::0850:mn-Mong-CN
::0851:bo-BT
::0859:sd-Arab-PK
::085D:iu-Latn-CA
::085F:tzm-Latn-DZ
::0860:ks-Deva
::0861:ne-IN
::0867:ff-Latn-SN
::086B:quz-EC
::0873:ti-ER
::09FF:qps-plocm
::0C01:ar-EG
::0C04:zh-HK
::0C07:de-AT
::0C09:en-AU
::0C0A:es-ES
::0C0C:fr-CA
::0C1A:sr-Cyrl-CS
::0C3B:se-FI
::0C50:mn-Mong-MN
::0C51:dz-BT
::0C5F:tmz-MA
::0C6b:quz-PE
::1001:ar-LY
::1004:zh-SG
::1007:de-LU
::1009:en-CA
::100A:es-GT
::100C:fr-CH
::101A:hr-BA
::103B:smj-NO
::105F:tzm-Tfng-MA
::1401:ar-DZ
::1404:zh-MO
::1407:de-LI
::1409:en-NZ
::140A:es-CR
::140C:fr-LU
::141A:bs-Latn-BA
::143B:smj-SE
::1801:ar-MA
::1809:en-IE
::180A:es-PA
::180C:fr-MC
::181A:sr-Latn-BA
::183B:sma-NO
::1C01:ar-TN
::1C09:en-ZA
::1C0A:es-DO
::1C1A:sr-Cyrl-BA
::1C3B:sma-SE
::2001:ar-OM
::2009:en-JM
::200A:es-VE
::200C:fr-RE
::201A:bs-Cyrl-BA
::203B:sms-FI
::2401:ar-YE
::2409:en-029
::240A:es-CO
::240C:fr-CD
::241A:sr-Latn-RS
::243B:smn-FI
::2801:ar-SY
::2809:en-BZ
::280A:es-PE
::280C:fr-SN
::281A:sr-Cyrl-RS
::2C01:ar-JO
::2C09:en-TT
::2C0A:es-AR
::2C0C:fr-CM
::2C1A:sr-Latn-ME
::3001:ar-LB
::3009:en-ZW
::300A:es-EC
::300C:fr-CI
::301A:sr-Cyrl-ME
::3401:ar-KW
::3409:en-PH
::340A:es-CL
::340C:fr-ML
::3801:ar-AE
::3809:en-ID
::380A:es-UY
::380C:fr-MA
::3c01:ar-BH
::3c09:en-HK
::3c0A:es-PY
::3c0C:fr-HT
::4001:ar-QA
::4009:en-IN
::400A:es-BO
::4401:ar-Ploc-SA
::4409:en-MY
::440A:es-SV
::4801:ar-145
::4809:en-SG
::480A:es-HN
::4C09:en-AE
::4C0A:es-NI
::5009:en-BH
::500A:es-PR
::5409:en-EG
::540A:es-US
::5809:en-JO
::580A:es-419
::5C09:en-KW
::5C0A:es-CU
::6009:en-TR
::6409:en-YE
::641A:bs-Cyrl
::681A:bs-Latn
::6C1A:sr-Cyrl
::701A:sr-Latn
::703B:smn
::742C:az-Cyrl
::743B:sms
::7804:zh
::7814:nn
::781A:bs
::782C:az-Latn
::783B:sma
::783F:kk-Cyrl
::7843:uz-Cyrl
::7850:mn-Cyrl
::785D:iu-Cans
::785F:tzm-Tfng
::7C04:zh-Hant
::7C14:nb
::7C1A:sr
::7C28:tg-Cyrl
::7C2E:dsb
::7C3B:smj
::7C3F:kk-Latn
::7C43:uz-Latn
::7C46:pa-Arab
::7C50:mn-Mong
::7C59:sd-Arab
::7C5C:chr-Cher
::7C5D:iu-Latn
::7C5F:tzm-Latn
::7C67:ff-Latn
::7C68:ha-Latn
::7C92:ku-Arab
::E40C:fr-015

Moving specific number of files into newly created numbered folders

I currently have around 550 files in a folder with the same format (.csv) and same headers (all started with the letters "YL").
I wonder if there is a way to splits these files (50 files at a time) (order doesn't matter) into numbered folders? (ex. 1, 2, 3, 4, 5) And also create a subsequent folder for the leftover files?
I have found this scripts and tried to modify it for 50 files, but it looks like it only created a the first folder (subdir1)
#echo off
set /a counter=1
set /a filesperfolder=50
cd dir\dir_main
:loopstart
set dirname=subdir%counter%
md %dirname%
echo %dirname%
dir /b | findstr /v /i "subdir*"> %temp%\temp.txt && for /l %%l in (1,1,%filesperfolder%) do #for /f "tokens=1,2* delims=:" %%a in ('findstr /n /r "^" %temp%\temp.txt ^| findstr /r "^%%l:"') do #move %%b %dirname%\%%b >nul
set /a counter=%counter%+1
for /f "tokens=*" %%a in ('type %temp%\temp.txt ^| find /c /v ""') do set _filesmoved=%%a
del %temp%\temp.txt
IF %_filesmoved% LSS 50 goto done
goto loopstart
:done
cls
echo All files were moved!!
pause
exit
I disliked the script you found as it was hard to read and used a temp file to keep track of the list of files. (Also, it evidently doesn't work, so there's that.)
#echo off
SET /a cnt=50
SET /a fnum=0
FOR /F "delims=" %%f IN ('dir /b /a-d *.csv') DO (
CALL :moveFile "%%f"
)
GOTO :end
:moveFile
IF "%cnt%" equ "50" CALL :makeDir
move "%~1" "%fnum%\%~1"
SET /a cnt+=1
GOTO :EOF
:makeDir
SET /a fnum+=1
mkdir %fnum%
SET /a cnt=0
GOTO :EOF
:end
Here is another way to do it. We test if there are still files in the directory, if there is, create a new directory and copy 50 files.
#echo off & setlocal enabledelayedexpansion
set fold_cnt=1
:test
set file_cnt=50
dir /a-d YL*.csv | findstr /IRC:"File(s)"
if %errorlevel% equ 0 (
mkdir !fold_cnt!
) else (
goto :eof
)
for %%i in (YL*.csv) do (
if not !file_cnt! equ 0 (
set /a file_cnt-=1
move /Y "%%i" "!fold_cnt!\%%i"
)
)
set /a fold_cnt+=1
goto test

How to remove names from a list in batch

I'm using windows bath, I have a list of names that I can add to but I don't know how to remove a name from the list.
So far my code is:
#echo off
setlocal enabledelayedexpansion
set allchoices=123456789
set "names=Bob,Steven,Harry"
set amount=6 ::max limit of list
set list=0
:start
::echoes a list of all names in the list
for /l %%i in (1; 1; %amount%) do (
call :sub %%i
)
goto check
:sub
for /f "tokens=%1 delims=," %%a in ("%names%") do (
echo %%i. %%a
set /a list=list+1
)
goto :eof
:check
::Remove a name from the list
choice /c !allchoices:~0,%list%! /m "What name do you want to remove?"
if errorlevel 3 (
for /f "tokens=3 delims=," %%a in ("%names%") do (
echo you have choosen to remove %%a
::remove third name in the list
goto start
)
)
if errorlevel 2 ::remove second name in the list
if errorlevel 1 ::remove first name in the list
I've tried using del but that turns out to delete a file in your folder.
I've tried renaming a specific name using set name[%%a]="" but that did nothing.
Any ideas?
Have a look at this example. There are many ways.
#echo off
setlocal enabledelayedexpansion
set names="Bob","Steven","Harry"
for %%i in (%names%) do (
set /a num+=1
set "!num!=%%~i"
)
for /l %%a in (1,1,%num%) do (
set choices=!choices!%%a
echo !num!.!%%a!
)
choice /c 123 /m "please select name to remove"
for /l %%a in (1,1,%num%) do if not "!%%a!"=="!%errorlevel%!" set new_names=!new_names! !%%~a!
echo %new_names:~1%
It can be done without the last for loop as well.. but I opted for it.
Here is some example code, for you to run, and then try to comprehend, I hope it helps rather than confuses:
#Echo Off
SetLocal EnableDelayedExpansion
For /F "Delims==" %%A In ('Set # 2^>NUL') Do Set "%%A="
Set "i=0"
For /F "Delims=:" %%A In ('FindStr "^::" "%~f0" 2^>NUL') Do (
Set /A i+=1
Set "#!i!=%%A"
Echo= !i!. %%A
)
:Ask
Set # 1>NUL 2>&1
If ErrorLevel 1 Echo= Empty names list&Timeout 3 1>NUL&Exit /B
Echo=&Set /P "Option= Choose a name to remove>"
Set #|Findstr "^#%Option%=" 1>NUL||GoTo :Ask
Set "Name=!#%Option%!"
Echo= You've chosen to remove "%Name%"
Timeout 2 1>NUL
Set "#%Option%="
ClS
For /F "Tokens=1*Delims=#=" %%A In ('Set # 2^>NUL') Do Echo= %%A. %%B
GoTo Ask
::Alan
::Beth
::Cleo
::Dale
::Eric
::Faye
::Greg
::Hugh
::Inga
Important note:Please ensure, before saving the above content as a Windows Command Script, that there is a line return, (blank line), at the end.

Displaying skipped batch comments

So I wanted to have plaintext comments in my bat file with useage information at the top by skipping the text using goto but wanted to display the text as help info if say /? switch was used..
I managed to get the text to display with this method
#echo off
goto start
:help
some
text
here not commands
#echo off
goto:eof
:start
echo on && prompt $h && call :help 2>nul
which displays this:
some
text
here not commands
Does anyone know a way to remove the blank lines?
I typically begin lines with :: to indicate a comment, and ::: to indicate documentation. I can then use FOR /F with FINDSTR to easily print out the documentation, as long as no displayed documentation line begins with :.
#echo off
::Documentation
:::
:::some
:::text
:::here not commands
:::
:::
::Show help
call :help
exit /b
:help
for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do #echo(%%A
exit /b
If I have a lot of documentation, then I may put a GOTO :START at the top to improve script start-up time.
#echo off
goto :start
::Documentation
:::
:::some
:::text
:::here not commands
:::
:::
:start
::Show help
call :help
exit /b
:help
for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do #echo(%%A
exit /b
Another one! ;-)
#echo off
goto help-end
:help-start
some
text
here not commands
:help-end
if "%~1" neq "/?" goto exitHelp
set "start="
for /F "delims=:" %%a in ('findstr /N /B ":help" "%~F0"') do (
if not defined start (set "start=%%a") else set "end=%%a"
)
for /F "skip=%start% tokens=1* delims=:" %%a in ('findstr /N "^" "%~F0"') do (
if "%%a" equ "%end%" goto exitHelp
echo(%%b
)
:exitHelp
echo Normal process continue here
#rojo
like this?
#echo off
goto start
:help
call :heredoc help && goto helpend
some
text
here not commands
:helpend
goto:eof
:start
call :help
pause
:heredoc <uniqueIDX>
setlocal enabledelayedexpansion
set go=
for /f "delims=" %%A in ('findstr /n "^" "%~f0"') do (
set "line=%%A" && set "line=!line:*:=!"
if defined go (if #!line:~1!==#!go::=! (goto :EOF) else echo(!line!)
if "!line:~0,13!"=="call :heredoc" (
for /f "tokens=3 delims=>^ " %%i in ("!line!") do (
if #%%i==#%1 (
for /f "tokens=2 delims=&" %%I in ("!line!") do (
for /f "tokens=2" %%x in ("%%I") do set "go=%%x"
)
)
)
)
)
goto :EOF
Output:
some
text
here not commands
Press any key to continue . . .
It definitely works!

cmd and exclamation marks

the following code fails for folder names containing exclamation marks. I think I need DelayedExpansion enabled to handle the nested for loops. Any ideas to get this work? Thanks!
#echo off & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set "dest=%~dpn1"
IF "%1" equ "" Set "dest=%cd%"
set /a Folders=0
set /a FoldersWithSubFoldersAndFiles=0
set /a FoldersWithOnlyFiles=0
set /a FoldersWithOnlySubFolders=0
set /a FoldersEmpty=0
for /f "usebackq tokens=*" %%a in (`DIR /AD /S /B "%dest%"`) do (
Set /a Folders+=1
for /f "usebackq tokens=*" %%i in (`DIR "%%a" /A-D /B 2^>NUL^| FIND /C /V ""`) do (
Set NumberOfFiles=%%i
)
for /f "usebackq tokens=*" %%i in (`DIR "%%a" /AD /B 2^>NUL^| FIND /C /V ""`) do (
set NumberOfFolders=%%i
)
IF "!NumberOfFiles!" neq "0" IF "!NumberOfFolders!" neq "0" set /a FoldersWithSubFoldersAndFiles+=1
IF "!NumberOfFiles!" neq "0" IF "!NumberOfFolders!" equ "0" set /a FoldersWithOnlyFiles+=1
IF "!NumberOfFiles!" equ "0" IF "!NumberOfFolders!" neq "0" set /a FoldersWithOnlySubFolders+=1
IF "!NumberOfFiles!" equ "0" IF "!NumberOfFolders!" equ "0" (
set /a FoldersEmpty+=1
echo %%a is empty.
)
)
echo Found %Folders% folders below "%dest%".
echo %FoldersWithSubFoldersAndFiles% folders containing files and subfolders.
echo %FoldersWithOnlyFiles% folders containing files only.
echo %FoldersWithOnlySubFolders% folders containing subfolders only.
echo %FoldersEmpty% folders are empty.
endlocal
I see 3 simple solutions:
1) The slowest method is to use CALL so that you do not need delayed expansion within your loop.
#echo off & setlocal disableDelayedExpansion
set "dest=%~dpn1"
IF "%1" equ "" Set "dest=%cd%"
set /a Folders=0
set /a FoldersWithSubFoldersAndFiles=0
set /a FoldersWithOnlyFiles=0
set /a FoldersWithOnlySubFolders=0
set /a FoldersEmpty=0
for /f "usebackq tokens=*" %%a in (`DIR /AD /S /B "%dest%"`) do (
Set /a Folders+=1
for /f "usebackq tokens=*" %%i in (`DIR "%%a" /A-D /B 2^>NUL^| FIND /C /V ""`) do (
Set NumberOfFiles=%%i
)
for /f "usebackq tokens=*" %%i in (`DIR "%%a" /AD /B 2^>NUL^| FIND /C /V ""`) do (
set NumberOfFolders=%%i
)
call :incrementCounts
)
echo Found %Folders% folders below "%dest%".
echo %FoldersWithSubFoldersAndFiles% folders containing files and subfolders.
echo %FoldersWithOnlyFiles% folders containing files only.
echo %FoldersWithOnlySubFolders% folders containing subfolders only.
echo %FoldersEmpty% folders are empty.
echo See dircount.log for list of empty folders.
endlocal
exit /b
:incrementCounts
IF "%NumberOfFiles%" neq "0" IF "%NumberOfFolders%" neq "0" set /a FoldersWithSubFoldersAndFiles+=1
IF "%NumberOfFiles%" neq "0" IF "%NumberOfFolders%" equ "0" set /a FoldersWithOnlyFiles+=1
IF "%NumberOfFiles%" equ "0" IF "%NumberOfFolders%" neq "0" set /a FoldersWithOnlySubFolders+=1
IF "%NumberOfFiles%" equ "0" IF "%NumberOfFolders%" equ "0" (
set /a FoldersEmpty+=1
echo %%a is empty.
)
exit /b
2) A faster method is to temporarily enable delayed expansion only long enough to transfer the values to FOR variables.
#echo off & setlocal disableDelayedExpansion
set "dest=%~dpn1"
IF "%1" equ "" Set "dest=%cd%"
set /a Folders=0
set /a FoldersWithSubFoldersAndFiles=0
set /a FoldersWithOnlyFiles=0
set /a FoldersWithOnlySubFolders=0
set /a FoldersEmpty=0
for /f "usebackq tokens=*" %%a in (`DIR /AD /S /B "%dest%"`) do (
Set /a Folders+=1
for /f "usebackq tokens=*" %%i in (`DIR "%%a" /A-D /B 2^>NUL^| FIND /C /V ""`) do (
Set NumberOfFiles=%%i
)
for /f "usebackq tokens=*" %%i in (`DIR "%%a" /AD /B 2^>NUL^| FIND /C /V ""`) do (
set NumberOfFolders=%%i
)
setlocal enableDelayedExpansion
for /f "tokens=1,2" %%N in ("!NumberOfFiles! !NumberOfFolders!") do (
endlocal
IF "%%N" neq "0" IF "%%M" neq "0" set /a FoldersWithSubFoldersAndFiles+=1
IF "%%N" neq "0" IF "%%M" equ "0" set /a FoldersWithOnlyFiles+=1
IF "%%N" equ "0" IF "%%M" neq "0" set /a FoldersWithOnlySubFolders+=1
IF "%%N" equ "0" IF "%%M" equ "0" (
set /a FoldersEmpty+=1
echo %%a is empty.
)
)
)
echo Found %Folders% folders below "%dest%".
echo %FoldersWithSubFoldersAndFiles% folders containing files and subfolders.
echo %FoldersWithOnlyFiles% folders containing files only.
echo %FoldersWithOnlySubFolders% folders containing subfolders only.
echo %FoldersEmpty% folders are empty.
echo See dircount.log for list of empty folders.
endlocal
3) But the way I would handle it is to eliminate the 2 variables that are only used within the loop. They aren't used outside the loop, and they are already derived from FOR variables. Since everything is now a FOR variable, you no longer need delayed expansion.
#echo off & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set "dest=%~dpn1"
IF "%1" equ "" Set "dest=%cd%"
set /a Folders=0
set /a FoldersWithSubFoldersAndFiles=0
set /a FoldersWithOnlyFiles=0
set /a FoldersWithOnlySubFolders=0
set /a FoldersEmpty=0
for /f "usebackq tokens=*" %%a in (`DIR /AD /S /B "%dest%"`) do (
Set /a Folders+=1
for /f "usebackq tokens=*" %%N in (`DIR "%%a" /A-D /B 2^>NUL^| FIND /C /V ""`) do (
for /f "usebackq tokens=*" %%M in (`DIR "%%a" /AD /B 2^>NUL^| FIND /C /V ""`) do (
IF "%%N" neq "0" IF "%%M" neq "0" set /a FoldersWithSubFoldersAndFiles+=1
IF "%%N" neq "0" IF "%%M" equ "0" set /a FoldersWithOnlyFiles+=1
IF "%%N" equ "0" IF "%%M" neq "0" set /a FoldersWithOnlySubFolders+=1
IF "%%N" equ "0" IF "%%M" equ "0" (
set /a FoldersEmpty+=1
echo %%a is empty.
)
)
)
)
echo Found %Folders% folders below "%dest%".
echo %FoldersWithSubFoldersAndFiles% folders containing files and subfolders.
echo %FoldersWithOnlyFiles% folders containing files only.
echo %FoldersWithOnlySubFolders% folders containing subfolders only.
echo %FoldersEmpty% folders are empty.
echo See dircount.log for list of empty folders.
endlocal

Resources