Count the underscores in the Filename with a bat - windows

I have searched this everywhere and I didn't found it, so what I want to do is simple, I want to count the underscores in a filename and put it in a variable to later use it.
Is there any simple batch code to do it ?

#echo off
setlocal enabledelayedexpansion
set filename=__example_file.bin_
set cnt=0
set pos=0
:loop
if "!filename:~%pos%,1!"=="_" set /a cnt=%cnt%+1
set /a pos=%pos%+1
if not "!filename:~%pos%,1!"=="" goto loop
echo Count: %cnt%
That code is pretty ugly but I can't find a better way so far.

A different method to count underscores (or more exact elements separated by an underscore)
is to use self expanding code:
:: Q:\Test\2017\08\28\SO_45917406.cmd
#echo off & setlocal enabledelayedexpansion
set "FileName=example_file_name_20170828_181000.txt"
Set i=1&Set "FileName[!i!]=%FileName:_="&Set /a i+=1&Set "FileName[!i!]=%"
Echo Counted %i% underscore separated elements
Set FileName
Sample output:
> Q:\Test\2017\08\28\SO_45917406.cmd
Counted 5 underscore separated elements
FileName=example_file_name_20170828_181000.txt
FileName[1]=example
FileName[2]=file
FileName[3]=name
FileName[4]=20170828
FileName[5]=181000.txt

This solution is inspired from #xmcp :
#echo off
Rem The srting to count in the filename is the underscrore "_"
Rem we can of course set another one ;)
set "MyString=_"
setlocal enabledelayedexpansion
#for /f "delims=" %%a in ('Dir /b "%userprofile%\Desktop"') do (
set "filename=%%a"
set /a "cnt=0"
set /a "pos=0"
Call:Counting_String "!filename!" "%Mystring%"
)
pause & exit
::*********************************************************
:Counting_String <filename> <MyString>
set "filename=%~1"
set "string=%~2"
if /I "!filename:~%pos%,1!"=="%Mystring%" set /a cnt+=1
set /a pos+=1
if not "!filename:~%pos%,1!"=="" goto Counting_String
echo !filename!: [!cnt!] "%Mystring%"
exit /b
::*********************************************************

Related

Joining a list of numbers in a .txt file with ,[space]

Hi I managed to get the code below to create a list of numbers and place a comma at the end of each number created However, it has proven to be quite the challenge to get them on the same line separated by a ,[space]
#ECHO OFF
setlocal EnableDelayedExpansion
set _Output=%UserProfile%\Desktop\NumGen.txt
::only change these three lines
set "start=1" ::starts from this number
set "amount=10" ::amount of files created
set "length=5" ::length of fileNames
set "join_with=, " ::what to join each number with
set /a "last=%start%+%amount%"
for /l %%i in (%start%,1,%last%) do (
set "folderName=0000000000%%i"
set "folderName=!folderName:~-%length%!%join_with%"
>>"%_Output%" ECHO.!folderName!
)
pause
so my output at the moment is
00001,
00002,
00003,
00004,
00005,
00006,
00007,
00008,
00009,
00010,
00011,
However I would like it to be
00001, 00002, 00003, 00004, 00005, 00006, 00007, 00008, 00009, 00010, 00011
I have windows 10 64bit. Any help will be appreciated
echo is not able to do that. But there is a workaround, (ab)using the set command:
for /l %%i in (1,1,5) do (
<nul set /p "=%%i, "
)
echo(
After a long break I decided to give this another bash and presto. Success :-)
::CallScript
#ECHO OFF
CALL :ScriptA
CALL :ScriptB
CALL :ScriptC
pause
goto :eof
:ScriptA
#ECHO OFF
setlocal EnableDelayedExpansion
set _Output=%UserProfile%\Desktop\NumGen.txt
::only change these three lines
set "start=1"
set "amount=10"
set "length=5"
set "join_with=, "
set /a "last=%start%+%amount%"
for /l %%i in (%start%,1,%last%) do (
set "folderName=0000000000%%i"
set "folderName=!folderName:~-%length%!%join_with%"
>>"%_Output%" ECHO.!folderName!
)
goto :eof
:ScriptB
#ECHO OFF
setlocal enableextensions enabledelayedexpansion
set "var="
for /f "usebackq delims=" %%a in ("%UserProfile%\Desktop\NumGen.txt") do set "var=!var!%%a"
echo %var%> "%UserProfile%\Desktop\NumList.txt"
goto :eof
:ScriptC
#ECHO OFF
del "%UserProfile%\Desktop\NumGen.txt"
goto :eof
This code determines the starting number, the amount of numbers, the length of the numbers and joins them with , "
Then ScriptB concatenates each number together with the , " and saves to NumList.txt
Lastly the script deletes the NumGen.txt file.
Stephan has one solution with SET /P. The other option is to build the entire string within an environment variable, and then write after the loop ends. This is significantly faster, but it will fail if the final string length exceeds ~8191 bytes.
set "str="
for /l %%i in (%start%,1,%last%) do (
set "folderName=0000000000%%i"
set "str=!str!!folderName:~-%length%!%join_with%"
)
>>"%_Output%" ECHO.!str!
You could remove the unwanted trailing , if you want:
>>"%_Output%" ECHO.!str:~0,-2!

Batch: Replacement for goto loop

When I'm writing batch programs I tend to create a goto loop to set and display things.
Example:
#echo off & setlocal enabledelayedexpansion
:loop
if !num! GTR !max!
set /a "num=num+1"
echo display!num! = !display%num%!
goto :loop
I had a feeling that I can replace this with a for loop, but I had no success creating one that can replace the loop above. Does anyone know?
You can use a for /L loop.
for /L %%A in (!num!,1,!max!) do echo display%%A = !display%%A!
Where !num! is your starting number, !max! is your ending number, and 1 means count up by ones.
#echo off
setlocal enableextensions enabledelayedexpansion
rem Set limits
set /a "num=1", "max=10"
rem Prepare a set of variables to test
for /l %%a in (%num% 1 %max%) do set "display%%a=!random!"
rem Show the variables contents
for /l %%a in (%num% 1 %max%) do echo display%%a=!display%%a!

Windows Batch File can't use variable in for syntax

I want to use a variable skip parameter in for loop, but it won't let me do it.
Here is my code
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
for /f "%skip%" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
)
Here skip is skip=1, but it doesn't skip any line. When I replace it with skip=1. then it works fine, but I want to skip variable no. of lines in each iteration. Please help.
I think with this logic the only option is a subroutine:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
call :innerFor %%P
)
exit /b 0
:innerFor
for /f "skip=%~1" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
exit /b 0
parametrization of FOR /F options is a little bit tricky..
Though I have no the content of your files I cant test if this works correctly .

Windows Batch: Split String to individual characters to variables

in Windows Batch, if I had a variable (length can change) that was, for example: "hello world!"
is it possible to "split" the variable so each character is its own variable so the output could look like:
t1=h
t2=e
t3=l
etc.
Any help would be appreciated.
Use this code:
setlocal EnableDelayedExpansion
set str="hello world^!"
set tempstr=%str%
set count=0
:loop
if defined tempstr (
set tempstr=%tempstr:~1%
set /a count+=1
set /a pos=%count%-1
set t!count!=!str:~%pos%,1!
goto loop
)
:: check the generated variables
set t
To get the nth character in a string, use set char=%str:~n,1%.
I hope this was helpful!
Here is a variant using for /L to iterate over all characters of the string. The number of characters, so the length of the string, is retrieved in sub-routine :LENGTH first:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_STRING=Hello world!"
call :LENGTH LEN "%_STRING%"
setlocal EnableDelayedExpansion
for /L %%I in (0,1,%LEN%) do (
set "$CHR[%%I]=!_STRING:~%%I,1!"
)
set $CHR
endlocal
endlocal
exit /B
:LENGTH rtn_length val_string
setlocal DisableDelayedExpansion
set /A "RET=0" & set "STR=%~2"
if defined STR set /A "RET=1"
setlocal EnableDelayedExpansion
for %%L in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if not "!STR:~%%L,1!"=="" (
set /A "RET+=%%L"
set "STR=!STR:~%%L!"
)
)
(
endlocal
endlocal
set "%~1=%RET%"
)
exit /B
Here is a different variant, using cmd /U to convert the string into Unicode, where a null-byte becomers inserted behind every character, and find, which treats these null-bytes like end-of-line markers:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_STRING=Hello world!"
set /A "IDX=0"
for /F delims^=^ eol^= %%I in ('
cmd /U /V /C echo^(!_STRING!^| find /V ""
') do (
set "CHR=%%I"
setlocal EnableDelayedExpansion
for /F "delims=" %%J in ("$CHR[!IDX!]=!CHR!") do (
endlocal
set "%%J"
)
set /A "IDX+=1"
)
set $CHR
endlocal
exit /B
Finally, here is another variant, based on a goto loop. This uses a position pointer POS to scan the string and to extract a single character. If no character is returned, the end of the string is reached:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_STRING=Hello world!"
setlocal EnableDelayedExpansion
if not defined _STRING goto :QUIT
set /A "POS=0"
:LOOP
set "CHR=!_STRING:~%POS%,1!"
if defined CHR (
set "$CHR[%POS%]=!CHR!"
set /A "POS+=1"
goto :LOOP
)
:QUIT
set $CHR
endlocal
endlocal
exit /B
Old thread, but accepted answer misses letter d?
Changed
set /a pos=%count%-1 to
set /a pos=!count!-1
setlocal EnableDelayedExpansion
set str="hello world!"
set tempstr=%str%
set count=0
:loop
if defined tempstr (
set tempstr=%tempstr:~1%
set /a count+=1
set /a pos=!count!-1
set t!count!=!str:~%pos%,1!
goto loop
)
:: check the generated variables
set t
pause
Here is another version.
variables start with 0, though
setlocal EnableDelayedExpansion
set var="hello world!"
rem remove quotes
set var=%var:"=%
rem add limiter
set var=%var%_
echo %var%
set count=0
:loop
set tempvar=!var:~%count%,1!
if !tempvar!==_ goto skip
set arr!count!=!tempvar!
set /a count=!count!+1
goto loop
:skip
echo out
echo display output
set arr
pause

Batch encoding text files

I have this code to read a text file.
#ECHO OFF
SetLocal EnableDelayedExpansion
for /f "delims=" %%x in ('type text.txt') do (
set "Var=%%x"
ECHO !Var!
)
pause
My question is that if i could advance every char in the file by 20 places like "a" would be "t". it can have numbers and symbols too. the txt file is 400 line long and there is between 1 and 120 char per line. does any one know how i could do this.
Sorry, this will not handle all the posibilities, but
#echo off
setlocal enableextensions disabledelayedexpansion
call :setTables
set "inputFile=inputFile.txt"
for /f "usebackq delims=*" %%a in ("%inputFile%") do (
set "data=%%a"
call :handleProblems
set "out="
setlocal enabledelayedexpansion
for /f "delims=" %%b in ('cmd /v:off /q /u /c "echo(!data!"^|more') do (
if defined "%%b" (
set "out=!out!!"%%b"!"
) else (
set "out=!out!%%b"
)
)
echo(!out!
endlocal
)
exit /b
:handleProblems
set "data=%data:!=~%"
set "data=%data:<=^<%"
set "data=%data:>=^>%"
set "data=%data:&=^&%"
set "data=%data:|=^|%"
set "data=%data:)=^)%"
exit /b
:setTables
set ""a"=t"
set ""b"=u"
set ""c"=v"
set ""d"=w"
set ""e"=x"
set ""f"=y"
set ""g"=z"
set ""h"=a"
set ""i"=b"
set ""j"=c"
set ""k"=d"
set ""l"=e"
set ""m"=f"
set ""n"=g"
set ""o"=h"
set ""p"=i"
set ""q"=j"
set ""r"=k"
set ""s"=l"
set ""t"=m"
set ""u"=n"
set ""v"=o"
set ""w"=p"
set ""x"=q"
set ""y"=r"
set ""z"=s"
set ""~"=!"
set ""^&"=&"
exit /b
Use GnuSed and the "y/abc/tuv/" transliteration command which would replace a with t, b with u and c with v
This syntax works - just extend the character sets:
sed "y/abc/tuv/" "file.txt" >"newfile.txt"

Resources