Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do you increment the alphabet in a variable?

1,039 views
Skip to first unread message

Zak Hipp

unread,
Nov 15, 2012, 2:48:53 PM11/15/12
to
I clone various directories to various external devices (without drive letter assignment concerns) with a compiled
executable of the script below. It works as intended, but have not found a way to increment the alphabet.

I've browsed the newsgroup (2012),FAQ, and 'tsbat.zip'; hoping not missed.

My aim is to increment the variable %drv% - e.g. drv=H drv=I ... etc.

Hope I've given enough information: WinXp-Sp2

Thank you in advance for any pointers.

----------------------------
@echo off

set ffsync=n:\freefilesync\freefilesync.exe
set batch=portable-
set ext=.ffs_batch
set count=0
set drives=19

:next

set /a count=%count%+1

if %count% GTR %drives% goto end
if %count% LEQ 9 set pad=0
if %count% GTR 9 set pad=

set drv=H
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=I
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=J
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=K
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=L
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=M
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=N
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=O
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=P
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=Q
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=R
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=S
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=T
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=U
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=V
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=W
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=X
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=Y
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync
set drv=Z
if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync

goto next

:sync
%drv%:
"%ffsync%" "%drv%:\%batch%%pad%%count%%ext%"

goto next

:end
----------------------------


Zak Hipp





frank.w...@gmail.com

unread,
Nov 15, 2012, 3:12:50 PM11/15/12
to
From Zak Hipp :
>My aim is to increment the variable %drv% - e.g. drv=H
>drv=I ... etc.


>if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync

FOR %%a in (H I J K [etc]) do (
If EXIST "%%a:" GOTO :sync
)


Frank

frank.w...@gmail.com

unread,
Nov 15, 2012, 3:19:58 PM11/15/12
to
From frank.westlake:
For your usage I guess you would CALL instead of GOTO.

Frank

Zak Hipp

unread,
Nov 15, 2012, 3:52:55 PM11/15/12
to
That looks to have taken you several microseconds to solve. :)

Thank you very much for your speedy reply.


Zak Hipp


Zak Hipp

unread,
Nov 15, 2012, 7:28:08 PM11/15/12
to
On 15/11/2012 20:19, frank.w...@gmail.com wrote:
I tried CALL, but I couldn't find a way for the %%a variable to cross over. The one below works. I couldn't avoid using
GOTO because although SET /a count=%count%+1 is working, FOR seems to be set to the value of %count% when initiated and
ignores changes to %count%.

------------------
@echo off

SET ffsync=n:\freefilesync\freefilesync.exe
SET batch=portable-
SET ext=.ffs_batch
SET count=0

:next
SET /a count=%count%+1

FOR %%a IN (H I J K L M N O P Q R S T U V W X Y Z) DO (
IF %count% LEQ 9 SET pad=0
IF %count% GTR 9 SET pad=
%%a:
IF EXIST %%a:\%batch%%pad%%count%%ext% %ffsync% %batch%%pad%%count%%ext%
)

IF %count% LEQ 18 GOTO next
------------------

Thank you again for the assist.


Zak Hipp


frank.w...@gmail.com

unread,
Nov 15, 2012, 7:29:40 PM11/15/12
to
From Zak Hipp :
>I tried CALL, but I couldn't find a way for the %%a
>variable to cross over.

There are two ways:

1. Place it on the command line and recieve it in the
subroutine:

CALL :sub "%%a:\dir"

:sub
SET "dir=%~1"

2. Set it into a variable directly and just use the
variable in the subroutine.


>The one below works. I couldn't
>avoid using GOTO because although SET /a count=%count%+1
>is working, FOR seems to be set to the value of %count%
>when initiated and ignores changes to %count%.

>FOR %%a IN (H I J K L M N O P Q R S T U V W X Y Z) DO (
>IF %count% LEQ 9 SET pad=0
>IF %count% GTR 9 SET pad=
>%%a:
>IF EXIST %%a:\%batch%%pad%%count%%ext% %ffsync%
>%batch%%pad%%count%%ext%
>)

All statements in parentheses get read only once and all
variable substitutions are nade then. To have the
substitutions made each time the variable is used use
delayed expansion. Replace all "%variable%" with
"!variable!", but not "%%a" to "!!a", and start your
script with:

SetLocal EnableDelayedExpansion

Frank

Zak Hipp

unread,
Nov 15, 2012, 8:05:21 PM11/15/12
to
On 16/11/2012 00:29, frank.w...@gmail.com wrote:
> From Zak Hipp :

[snipped of brevity]

Thank you Frank.


billious

unread,
Nov 15, 2012, 9:03:47 PM11/15/12
to
How about


@ECHO OFF
SETLOCAL
set ffsync=n:\freefilesync\freefilesync.exe
FOR /l %%i IN (101,1,119) DO CALL :synch %%i
GOTO :eof

:: entering SYNCH with parameter 101..119
:synch
SET drv=%1
SET /a count=%1-100
SET count=SET drv=%%drv:~%count%,1%%:\portable-%drv:~-2%.ffs_batch
SET drv=xHIJKLMNOPQRSTUVWXYZ
CALL %count%
ECHO IF EXIST "%drv%" %drv:~0,2%^&"%ffsync%" "%drv%"
GOTO :eof

Each line indented 2 spaces. Any line not starting with 2 spaces has
been wrapped.

Note that this will simply ECHO the command. After verification, to
execute remove the ECHO keyword from the second-last line AND remove the
caret before the "&".

Zak Hipp

unread,
Nov 16, 2012, 4:28:38 PM11/16/12
to
On 16/11/2012 02:03, billious wrote:
> On 16/11/2012 03:48, Zak Hipp wrote:
>> I clone various directories to various external devices (without drive
>> letter assignment concerns)

>> My aim is to increment the variable %drv% - e.g. drv=H drv=I ... etc.

>> set drv=H
>> if exist "%drv%:\%batch%%pad%%count%%ext%" goto sync

>> :sync
>> %drv%:
>> "%ffsync%" "%drv%:\%batch%%pad%%count%%ext%"
>
> How about
>
>
> @ECHO OFF
> SETLOCAL
> set ffsync=n:\freefilesync\freefilesync.exe
> FOR /l %%i IN (101,1,119) DO CALL :synch %%i
> GOTO :eof
>
> :: entering SYNCH with parameter 101..119
> :synch
> SET drv=%1
> SET /a count=%1-100
> SET count=SET drv=%%drv:~%count%,1%%:\portable-%drv:~-2%.ffs_batch
> SET drv=xHIJKLMNOPQRSTUVWXYZ
> CALL %count%
> ECHO IF EXIST "%drv%" %drv:~0,2%^&"%ffsync%" "%drv%"
> GOTO :eof

Thank you for the effort you've put in; much appreciated.

There are a couple of things that you could not know about:

1) Must be at drive (H: etc.) for %ffsync% to work:

<FolderPairs>
<Pair>
<Left>N:\Installers</Left>
<Right>\</Right>
</Pair>
</FolderPairs>

2) It must search each drive for all values of %count% (19^2).

I have made organisational changes to the way my backup system is implemented to not need 361 drive searches; simply by
naming them all 'portable.ffs_batch' and ensuring the same file is not copied to more than one device.

Now I know what your translation does; will make it far easier to learn how it does it. Anyway, this is the latest hot
off the press v4.0.1.23 :)

---------------
@ECHO OFF
SET ffsync=n:\freefilesync\freefilesync.exe
SET batch=portable.ffs_batch
FOR %%a IN (H I J K L M N O P Q R S T U V W X Y Z) DO (
IF NOT EXIST %%a:\portable.ffs_batch CALL :skip
%%a:
IF EXIST %%a:\%batch% %ffsync% %batch%
)
:skip
---------------

Grateful.


Zak Hipp


frank.w...@gmail.com

unread,
Nov 16, 2012, 4:33:40 PM11/16/12
to
From Zak Hipp :
>---------------
>@ECHO OFF
>SET ffsync=n:\freefilesync\freefilesync.exe
>SET batch=portable.ffs_batch
>FOR %%a IN (H I J K L M N O P Q R S T U V W X Y Z) DO (
>IF NOT EXIST %%a:\portable.ffs_batch CALL :skip
>%%a:
>IF EXIST %%a:\%batch% %ffsync% %batch%
>)
>:skip

It looks like that last line was just thrown in to show
us that there is a subroutine named "skip". But if that
is truely where the subroutine begins then you should
precede it with a GOTO :EOF to keep it from being
executed every time FOR completes. In general:

:main
:: code
GOTO EOF

:sub1
:: code
GOTO :EOF

:sub2
:: code
GOTO :EOF

Frank

Zak Hipp

unread,
Nov 16, 2012, 5:13:32 PM11/16/12
to
Noted. Thank you.


Zak Hipp


Zak Hipp

unread,
Nov 16, 2012, 6:57:44 PM11/16/12
to
On 16/11/2012 21:33, frank.w...@gmail.com wrote:
> From Zak Hipp :

There was an error that CALL solved. This will eventually, in some form, be a :sub

@ECHO OFF
SET ffsync=n:\freefilesync\freefilesync.exe
SET ffs=ffs.ffs_batch
FOR %%a IN (H I J K L M N O P Q R S T U V W X Y Z) DO (
IF EXIST %%a:\%ffs% %%a:
IF EXIST %%a:\%ffs% %ffsync% %%a:\%ffs%
)

Thank you Frank and billious.



Zak Hipp


Stan Dandy Liver

unread,
Nov 19, 2012, 12:16:42 PM11/19/12
to
On Fri, 16 Nov 2012 21:28:38 -0000, Zak Hipp <Z...@invalid.invalid> wrote:


>
[]

> FOR %%a IN (H I J K L M N O P Q R S T U V W X Y Z) DO (


I know we (well I anyway) always used to do this because there was no
other way in msdos batch, but surely it's possible in cmd to increment a
letter -

{some furtling around the web and cmd prompt help later}

I see it's possible using =ExitCodeAscii, but that means invoking a
separate cmd process each time.
OK I'll stick to typing the letters in!


I bet Herbert would've done it in ASCII asm.

--
[dash dash space newline 4line sig]

Money/Life question

frank.w...@gmail.com

unread,
Nov 19, 2012, 1:08:59 PM11/19/12
to
From "Stan Dandy Liver" :
>... surely it's
>possible in cmd to increment a letter

Yes. I don't have a console handy to get it right, but
something like this:


Set "A=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Set /A "n=0"

:loop
Set "Drv=%A:~!n!,1"
If EXIST "%Drv%:\path\file" etc...

Set /A "n+=1"

Frank

Frank Westlake

unread,
Nov 19, 2012, 1:24:03 PM11/19/12
to
This works:

@Echo OFF
SetLocal EnableExtensions EnableDelayedExpansion
Set "A=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Set /A "n=0"

:loop
Set "Drv=!A:~%n%,1!"
echo %Drv%:

Set /A "n+=1"
If %n% LEQ 10 goto :loop
Goto :EOF

Frank

Zak Hipp

unread,
Nov 19, 2012, 2:54:29 PM11/19/12
to
On 19/11/2012 17:16, Stan Dandy Liver wrote:
> On Fri, 16 Nov 2012 21:28:38 -0000, Zak Hipp <Z...@invalid.invalid> wrote:
>
>
>>
> []
>
>> FOR %%a IN (H I J K L M N O P Q R S T U V W X Y Z) DO (
>
>
> I know we (well I anyway) always used to do this because there was no other way in msdos batch, but surely it's possible
> in cmd to increment a letter -
>
> {some furtling around the web and cmd prompt help later}
>
> I see it's possible using =ExitCodeAscii, but that means invoking a separate cmd process each time.
> OK I'll stick to typing the letters in!
>
>
> I bet Herbert would've done it in ASCII asm.

I went down the ASCII code route so I could use SET /a

As you can see, I'm really up for it. :)


Zak Hipp


Zak Hipp

unread,
Nov 19, 2012, 2:56:28 PM11/19/12
to
It's a real treat watching people who now their stuff at work.


Zak Hipp


Frank Westlake

unread,
Nov 19, 2012, 4:58:53 PM11/19/12
to
On 2012-11-19 09:16, Stan Dandy Liver wrote:
> ... surely it's possible in cmd to increment a letter

If you can't use DELAYEDEXPANSION then it's still just as simple:

@Echo OFF
SetLocal EnableExtensions
Set "A=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Set /A "n=0"

:loop
CALL Set "Drv=%%A:~%n%,1%%"
REM Double ^^ ^^

Stan Dandy Liver

unread,
Nov 19, 2012, 6:08:19 PM11/19/12
to
Sorry, what I meant was some kind of (it's late here and I'm not as keen a
coder as I used to be - what, who counted the beers?) - but I meant to
avoid typing the letters in.

Oh alright; some idea of code:

for /l %%a in (65,1,68) do (
cmd /c exit /b %%a
echo "%=ExitCodeAscii%"
)


but there's some problem.

foxidrive

unread,
Nov 19, 2012, 6:51:50 PM11/19/12
to
On 20/11/2012 10:08, Stan Dandy Liver wrote:
> Sorry, what I meant was some kind of (it's late here and I'm not as keen a
> coder as I used to be - what, who counted the beers?) - but I meant to
> avoid typing the letters in.
>
> Oh alright; some idea of code:
>
> for /l %%a in (65,1,68) do (
> cmd /c exit /b %%a
> echo "%=ExitCodeAscii%"
> )
>
>
> but there's some problem.



@echo off
for /l %%a in (65,1,90) do (
cmd /c exit /b %%a
call echo "%%=ExitCodeAscii%%"
)
pause


--
foxi

Frank Westlake

unread,
Nov 19, 2012, 6:56:04 PM11/19/12
to
On 2012-11-19 15:08, Stan Dandy Liver wrote:
> I meant to avoid typing the letters in.

Like most scripting languages can do.

CMD script is like C, both of them are both mid level and low level
languages, except that CMD does not differentiate data types (although
it does often make guesses).

In the low-level arena of CMD (like C and assembly) you must combine
low-level statements into a subroutine and use that subroutine as if it
were a mid-level command. So in CMD you would define a character
subroutine of your own, perhaps something like this:

@Echo OFF
SetLocal EnableExtensions EnableDelayedExpansion

REM Set specific character:
For /L %%i in (65,1,90) Do (
CALL :setChar drv %%i
echo !Drv!:
)
Goto :EOF

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:setChar var ASCII_value
Set "setChar.chars=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Set /A "setChar.index= %~2 - 91"
Set "%~1=!setChar.chars:~%setChar.index%,1!
Goto :EOF
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Frank

Frank Westlake

unread,
Nov 20, 2012, 6:07:37 AM11/20/12
to
On 2012-11-19 15:08, Stan Dandy Liver wrote:
> I meant to avoid typing the letters in.

I think this 'setChar' subroutine will properly set the variable with
any character from space (32) to ~ (126).

@Echo OFF
SetLocal EnableExtensions EnableDelayedExpansion

REM Set specific character:
For /L %%i in (32,1,126) Do (
CALL :setChar c=%%i
echo;!c!
)
Goto :EOF

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:setChar variable_name ASCII_value
IF %~2 EQU 33 (
"%ComSpec%" /c EXIT /b 33
Call Set "%~1=%%=ExitCodeAscii%%"
Goto :EOF
)
IF %~2 EQU 37 (Set "%~1=%%"& Goto :EOF)
IF %~2 EQU 39 (Goto :setChar.quote)
Set "setChar.chars= E'#$P&Q()*+,-./0123456789:;<=>?@"
Set "setChar.chars=!setChar.chars!ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`"
Set "setChar.chars=!setChar.chars!abcdefghijklmnopqrstuvwxyz{|}~"
Set /A "setChar.index= %~2 - 32"
Set "%~1=!setChar.chars:~%setChar.index%,1!
Goto :EOF
:setChar.quote
Set %~1="
Goto :EOF
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Frank

foxidrive

unread,
Nov 20, 2012, 6:31:04 AM11/20/12
to
On 20/11/2012 10:51, foxidrive wrote:
> On 20/11/2012 10:08, Stan Dandy Liver wrote:
>> Sorry, what I meant was some kind of (it's late here and I'm not as keen a
>> coder as I used to be - what, who counted the beers?) - but I meant to
>> avoid typing the letters in.
>
>
> @echo off
> for /l %%a in (65,1,90) do (
> cmd /c exit /b %%a
> call echo "%%=ExitCodeAscii%%"
> )
> pause
>

Maybe Frank didn't try the above.



--
foxi

Timo Salmi

unread,
Nov 20, 2012, 3:25:59 PM11/20/12
to
On 19.11.2012 19:16 Stan Dandy Liver wrote:
> On Fri, 16 Nov 2012 21:28:38 -0000, Zak Hipp <Z...@invalid.invalid> wrote:
>> FOR %%a IN (H I J K L M N O P Q R S T U V W X Y Z) DO (

> I know we (well I anyway) always used to do this because there was no
> other way in msdos batch, but surely it's possible in cmd to increment a
> letter -

A task similar to
132) How to find out the next weekday given today's?
http://www.netikka.net/tsneti/info/tscmd132.htm

All the best, Timo

--
Prof. (emer.) Timo Salmi, Vaasa, Finland
http://www.netikka.net/tsneti/homepage.php
Useful CMD script tricks http://www.netikka.net/tsneti/info/tscmd.php

Stan Dandy Liver

unread,
Nov 20, 2012, 4:15:37 PM11/20/12
to
On Mon, 19 Nov 2012 23:56:04 -0000, Frank Westlake
<frank.w...@gmail.com> wrote:

> On 2012-11-19 15:08, Stan Dandy Liver wrote:
>> I meant to avoid typing the letters in.
>
> Like most scripting languages can do.
>
> CMD script is like C, both of them are both mid level and low level
> languages, except that CMD does not differentiate data types (although
> it does often make guesses).
>
> In the low-level arena of CMD (like C and assembly) you must combine
> low-level statements into a subroutine and use that subroutine as if it
> were a mid-level command. So in CMD you would define a character
> subroutine of your own, perhaps something like this:
>
> @Echo OFF
> SetLocal EnableExtensions EnableDelayedExpansion
>
> REM Set specific character:
> For /L %%i in (65,1,90) Do (
> CALL :setChar drv %%i
> echo !Drv!:
> )
> Goto :EOF
>
> ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
> :setChar var ASCII_value
> Set "setChar.chars=ABCDEFGHIJKLMNOPQRSTUVWXYZ"

ITYF you typed the alphabet in there!


> Set /A "setChar.index= %~2 - 91"
> Set "%~1=!setChar.chars:~%setChar.index%,1!
> Goto :EOF
> ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
>
> Frank
>


Stan Dandy Liver

unread,
Nov 20, 2012, 4:16:30 PM11/20/12
to
On Mon, 19 Nov 2012 23:51:50 -0000, foxidrive <n...@this.address.invalid>
wrote:
Thanks - I was getting lost with trying setlocal enabledelayedexpansion

Stan Dandy Liver

unread,
Nov 20, 2012, 4:24:32 PM11/20/12
to
On Tue, 20 Nov 2012 20:25:59 -0000, Timo Salmi <t...@uwasa.fi> wrote:

> On 19.11.2012 19:16 Stan Dandy Liver wrote:
>> On Fri, 16 Nov 2012 21:28:38 -0000, Zak Hipp <Z...@invalid.invalid> wrote:
>>> FOR %%a IN (H I J K L M N O P Q R S T U V W X Y Z) DO (
>
>> I know we (well I anyway) always used to do this because there was no
>> other way in msdos batch, but surely it's possible in cmd to increment
>> a letter -
>
> A task similar to
> 132) How to find out the next weekday given today's?
> http://www.netikka.net/tsneti/info/tscmd132.htm
>
> All the best, Timo
>
No, I'm fine with substringing text, it was (repeats) "incrementing a
letter" I wanted - but Foxidrive corrected my attempt.

It's not worth the candle - as has been suggested elsewhere - just keep a
standard rtn or line of text with all the letters in.

(History)

I think I first came across this kind of "search the letters" routine with
boot disks - the standard IBM vdisk.sys utility just assigned the next
letter to the ramdisk you created; fortunately later utilities allowed you
to specify which letter to assign (a good one was somewhere in the middle,
such as R for Ramdrive).

foxidrive

unread,
Nov 20, 2012, 11:27:59 PM11/20/12
to
On 21/11/2012 08:24, Stan Dandy Liver wrote:
> I think I first came across this kind of "search the letters" routine with
> boot disks - the standard IBM vdisk.sys utility just assigned the next
> letter to the ramdisk you created; fortunately later utilities allowed you
> to specify which letter to assign (a good one was somewhere in the middle,
> such as R for Ramdrive).

Back in the MSDOS days there were loads of error messages when searching non-existent drives so you also
had to redirect the console to NUL and restore it later, to get a clean screen.

It's far nicer these days...

--
foxi
0 new messages