:MoveObject :MoveArray quick function to move array element and objects

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
shodan
Posts: 54
Joined: 01 May 2023 01:49

:MoveObject :MoveArray quick function to move array element and objects

#1 Post by shodan » 16 Sep 2023 14:49

Hello,

I did a small array manipulation function

Works great but I'd like to improve it some more.

Here is the demo code

Code: Select all

:MoveObject-DEMO
set myarray[0]=Open Source, light and extremely simple,
set myarray[1]=It is a single executable file with no dependencies.
set myarray[2]=Just download it and add it to your PATH
set myarray[6]=Create, edit, copy, move, download your files easily,
set myarray[7]=everywhere, every time. Use it as your personal cloud.
set myarray.ubound=7

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS

echo.&echo Moving object [6] to [4]&echo.
call :moveobject myarray[6] myarray[4]

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS

echo.&echo Moving object [4] to [3]&echo.
call :moveobject myarray[4] myarray[3]

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS

echo.&echo Moving objects [1][2][3] to [4][5][6]&echo.
call :moveobject myarray[1] myarray[4]
call :moveobject myarray[2] myarray[5]
call :moveobject myarray[3] myarray[6]

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS

GoTo :EOF
The function itself

:MoveObject
for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" EQU "[%~1]" set %~2=%%b
for /f "tokens=1 delims==" %%a in ('set %~1. 2^>nul') do for /f "tokens=2 eol== delims=.=" %%b in ('set %%a 2^>nul') do for /f "tokens=2* delims==" %%c in ('set %%a 2^>nul') do set %~2.%%b=%%c
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1 2^>nul') do set %%a=
GoTo :EOF


Also related function DeleteObject

:DeleteObject
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1 2^>nul') do set %%a=
if "[%~2]" NEQ "[]" shift & GoTo :DeleteObject
GoTo :EOF
:DeleteObjectOnly
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1. 2^>nul') do set %%a=
if "[%~2]" NEQ "[]" shift & GoTo :DeleteObjectOnly
GoTo :EOF

Still need to add the DeleteArrayElement MoveArrayElement aliases to move only the element and not the object
Also to allow multiple object moves in one function call to MoveObject

Here is the output of the demo code

Code: Select all

MoveObject-DEMO.bat

Printing myarray

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:
5:
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

Moving object [6] to [4]


Printing myarray

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:Create, edit, copy, move, download your files easily,
5:
6:
7:everywhere, every time. Use it as your personal cloud.

Moving object [4] to [3]


Printing myarray

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:Create, edit, copy, move, download your files easily,
4:
5:
6:
7:everywhere, every time. Use it as your personal cloud.

Moving objects [1][2][3] to [4][5][6]


Printing myarray

0:Open Source, light and extremely simple,
1:
2:
3:
4:It is a single executable file with no dependencies.
5:Just download it and add it to your PATH
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

And I will attach the full test file
MoveObject-DEMO.zip
(2.67 KiB) Downloaded 89 times

shodan
Posts: 54
Joined: 01 May 2023 01:49

Re: :MoveObject :MoveArray quick function to move array element and objects

#2 Post by shodan » 16 Sep 2023 15:36

Here is an alternate demo which showcases the .suffix functionality of MoveObject

Code: Select all

:MoveObject-DEMO
set myarray[0]=Open Source, light and extremely simple,
set myarray[1]=It is a single executable file with no dependencies.
set myarray[2]=Just download it and add it to your PATH
set myarray[6]=Create, edit, copy, move, download your files easily,
set myarray[7]=everywhere, every time. Use it as your personal cloud.
set myarray[0].suffixA=test.sufA.0
set myarray[1].suffixA=test.sufA.1
set myarray[2].suffixA=test.sufA.2
set myarray[6].suffixA=test.sufA.6
set myarray[7].suffixA=test.sufA.7
set myarray.ubound=7

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
echo.&call :echoarray myarray .suffixA LINENUMBERS

echo.&echo Moving object [6] to [4]&echo.
call :moveobject myarray[6] myarray[4]

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
echo.&call :echoarray myarray .suffixA LINENUMBERS

echo.&echo Moving object [4] to [3]&echo.
call :moveobject myarray[4] myarray[3]

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
echo.&call :echoarray myarray .suffixA LINENUMBERS

echo.&echo Moving objects [1][2][3] to [4][5][6]&echo.
call :moveobject myarray[1] myarray[4]
call :moveobject myarray[2] myarray[5]
call :moveobject myarray[3] myarray[6]

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
echo.&call :echoarray myarray .suffixA LINENUMBERS

GoTo :EOF

And here its output

Code: Select all

MoveObject-DEMO.bat

Printing myarray

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:
5:
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:test.sufA.6
7:test.sufA.7

Moving object [6] to [4]


Printing myarray

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:Create, edit, copy, move, download your files easily,
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:test.sufA.6
5:
6:
7:test.sufA.7

Moving object [4] to [3]


Printing myarray

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:Create, edit, copy, move, download your files easily,
4:
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:test.sufA.6
4:
5:
6:
7:test.sufA.7

Moving objects [1][2][3] to [4][5][6]


Printing myarray

0:Open Source, light and extremely simple,
1:
2:
3:
4:It is a single executable file with no dependencies.
5:Just download it and add it to your PATH
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:
2:
3:
4:test.sufA.1
5:test.sufA.2
6:test.sufA.6
7:test.sufA.7
I have attached this newer version
MoveObject-DEMO.zip
(2.72 KiB) Downloaded 100 times

shodan
Posts: 54
Joined: 01 May 2023 01:49

Re: :MoveObject :MoveArray quick function to move array element and objects

#3 Post by shodan » 16 Sep 2023 15:56

However there is a special case where this does not work


If the "object" name contains a "." it messes up the demo.

Here is a new version of the demo function, which replaces "myarray" with "my.array"

Code: Select all

:MoveObject-DEMO2

set my.array[0]=Open Source, light and extremely simple,
set my.array[1]=It is a single executable file with no dependencies.
set my.array[2]=Just download it and add it to your PATH
set my.array[6]=Create, edit, copy, move, download your files easily,
set my.array[7]=everywhere, every time. Use it as your personal cloud.
set my.array[0].suffixA=test.sufA.0
set my.array[1].suffixA=test.sufA.1
set my.array[2].suffixA=test.sufA.2
set my.array[6].suffixA=test.sufA.6
set my.array[7].suffixA=test.sufA.7
set my.array.ubound=7

echo.&echo Printing my.array&echo.
call :echoarray my.array LINENUMBERS
echo.&call :echoarray my.array .suffixA LINENUMBERS

echo.&echo Moving object [6] to [4]&echo.
call :moveobject my.array[6] my.array[4]

echo.&echo Printing my.array&echo.
call :echoarray my.array LINENUMBERS
echo.&call :echoarray my.array .suffixA LINENUMBERS

echo.&echo Moving object [4] to [3]&echo.
call :moveobject my.array[4] my.array[3]

echo.&echo Printing my.array&echo.
call :echoarray my.array LINENUMBERS
echo.&call :echoarray my.array .suffixA LINENUMBERS

echo.&echo Moving objects [1][2][3] to [4][5][6]&echo.
call :moveobject my.array[1] my.array[4]
call :moveobject my.array[2] my.array[5]
call :moveobject my.array[3] my.array[6]

echo.&echo Printing my.array&echo.
call :echoarray my.array LINENUMBERS
echo.&call :echoarray my.array .suffixA LINENUMBERS

GoTo :EOF

Here is the output of that

Code: Select all

MoveObject-DEMO.bat

Printing my.array

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:
5:
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:test.sufA.6
7:test.sufA.7

Moving object [6] to [4]


Printing my.array

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:Create, edit, copy, move, download your files easily,
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:
7:test.sufA.7

Moving object [4] to [3]


Printing my.array

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:Create, edit, copy, move, download your files easily,
4:
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:
7:test.sufA.7

Moving objects [1][2][3] to [4][5][6]


Printing my.array

0:Open Source, light and extremely simple,
1:
2:
3:
4:It is a single executable file with no dependencies.
5:Just download it and add it to your PATH
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:
2:
3:
4:
5:
6:
7:test.sufA.7

So the base array element still work fine, but the .suffixA are getting deleted

A look at "set my" reveals this

Code: Select all

set my
my.array.ubound=7
my.array[0]=Open Source, light and extremely simple,
my.array[0].suffixA=test.sufA.0
my.array[4]=It is a single executable file with no dependencies.
my.array[4].array[1]=test.sufA.1
my.array[5]=Just download it and add it to your PATH
my.array[5].array[2]=test.sufA.2
my.array[6]=Create, edit, copy, move, download your files easily,
my.array[6].array[3]=test.sufA.6
my.array[7]=everywhere, every time. Use it as your personal cloud.
my.array[7].suffixA=test.sufA.7

So what is happenning is that everything after the first dot in the variable name is getting added after the variable name and the suffix .suffixA is lost.

I think I will need to parse the base variable name and if it contains a ".", run the code to split from the root variable name to the "="
That will slow things down a lot :(

I have modified and duplicated this line

Code: Select all

for /f "tokens=1 delims==" %%a in ('set %~1. 2^>nul') do for /f "tokens=2 eol== delims=.=" %%b in ('set %%a 2^>nul') do for /f "tokens=2* delims==" %%c in ('set %%a 2^>nul') do set %~2.%%b=%%c
to this

Code: Select all

for /f "tokens=1 delims==" %%a in ('set %~1. 2^>nul') do for /f "tokens=2 eol== delims=.=" %%b in ('set %%a 2^>nul') do for /f "tokens=2* delims==" %%c in ('set %%a 2^>nul') do echo %~2.%%b=%%c
So we can see the "set" part, I also commented out the echoarray for the base array without suffix

Here is the output again

Code: Select all

MoveObject-DEMO.bat

Printing my.array


0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:test.sufA.6
7:test.sufA.7

Moving object [6] to [4]

my.array[4].array[6]=test.sufA.6

Printing my.array


0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:
7:test.sufA.7

Moving object [4] to [3]

my.array[3].array[4]=test.sufA.6

Printing my.array


0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:
7:test.sufA.7

Moving objects [1][2][3] to [4][5][6]

my.array[4].array[1]=test.sufA.1
my.array[5].array[2]=test.sufA.2
my.array[6].array[3]=test.sufA.6

Printing my.array


0:test.sufA.0
1:
2:
3:
4:
5:
6:
7:test.sufA.7
So the important bits are these

Code: Select all

my.array[4].array[6]=test.sufA.6
my.array[3].array[4]=test.sufA.6
my.array[4].array[1]=test.sufA.1
my.array[5].array[2]=test.sufA.2
my.array[6].array[3]=test.sufA.6
Which should have been

Code: Select all

my.array[4].suffixA=test.sufA.6
my.array[3].suffixA=test.sufA.6
my.array[4].suffixA=test.sufA.1
my.array[5].suffixA=test.sufA.2
my.array[6].suffixA=test.sufA.6
I think what I will have to do is
When there is one of more "." in the base variable name (%~1)

my.array[4].suffixA=test.sufA.6

Split on the "="

my.array[4].suffixA

Remove base variable name

set var1=my.array[4].suffixA
var2=%var1:my.array[4]=%

And finally set destination plus suffix plus variable

set %~2%var2%=test.sufA.6

shodan
Posts: 54
Joined: 01 May 2023 01:49

Re: :MoveObject :MoveArray quick function to move array element and objects

#4 Post by shodan » 16 Sep 2023 16:22

To address the latest findings, I have modified the DEMO and :MoveObject functions

The DEMO function does not should the base array values, which are not a problem

The :MoveObject now has a loop which further parses the input variable to extract the base variable name from the .suffix

:MoveObject

Code: Select all

:MoveObject
set _MoveObject_Input=%~1
for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" EQU "[%~1]" set %~2=%%b
REM for /f "tokens=1 delims==" %%a in ('set %~1. 2^>nul') do for /f "tokens=2 eol== delims=.=" %%b in ('set %%a 2^>nul') do for /f "tokens=2* delims==" %%c in ('set %%a 2^>nul') do echo %~2.%%b=%%c
REM for /f "tokens=1 delims==" %%a in ('set %~1. 2^>nul') do for /f "tokens=1,2 eol== delims==" %%b in ('set %%a 2^>nul') do echo %~1 , %%a , %%b , %%c
REM for /f "tokens=1,2* delims==" %%a in ('set %~1. 2^>nul') do  echo %~1 , %%a , %%b
for /f "tokens=1,2* delims==" %%a in ('set %~1. 2^>nul') do  (
	setlocal enabledelayedexpansion
	set _var_name_buffer=%%a
	set _var_name_remain_buffer=!_var_name_buffer:%_MoveObject_Input%=!
	echo %_MoveObject_Input% , %%a , %%b , !_var_name_remain_buffer!
	echo new variable is %_MoveObject_Input%!_var_name_remain_buffer!
	echo set command should be set %_MoveObject_Input%!_var_name_remain_buffer!=%%b
	endlocal
	)
for /f "tokens=1 delims==" %%a in ('set %~1. 2^>nul') do for /f "tokens=2 eol== delims=.=" %%b in ('set %%a 2^>nul') do for /f "tokens=2* delims==" %%c in ('set %%a 2^>nul') do set %~2.%%b=%%c
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1 2^>nul') do set %%a=
GoTo :EOF
The DEMO2

Code: Select all

:MoveObject-DEMO2

set my.array[0]=Open Source, light and extremely simple,
set my.array[1]=It is a single executable file with no dependencies.
set my.array[2]=Just download it and add it to your PATH
set my.array[6]=Create, edit, copy, move, download your files easily,
set my.array[7]=everywhere, every time. Use it as your personal cloud.
set my.array[0].suffixA=test.sufA.0
set my.array[1].suffixA=test.sufA.1
set my.array[2].suffixA=test.sufA.2
set my.array[6].suffixA=test.sufA.6
set my.array[7].suffixA=test.sufA.7
set my.array.ubound=7

echo.&echo Printing my.array&echo.
REM call :echoarray my.array LINENUMBERS
echo.&call :echoarray my.array .suffixA LINENUMBERS

echo.&echo Moving object [6] to [4]&echo.
call :moveobject my.array[6] my.array[4]

echo.&echo Printing my.array&echo.
REM call :echoarray my.array LINENUMBERS
echo.&call :echoarray my.array .suffixA LINENUMBERS

echo.&echo Moving object [4] to [3]&echo.
call :moveobject my.array[4] my.array[3]

echo.&echo Printing my.array&echo.
REM call :echoarray my.array LINENUMBERS
echo.&call :echoarray my.array .suffixA LINENUMBERS

echo.&echo Moving objects [1][2][3] to [4][5][6]&echo.
call :moveobject my.array[1] my.array[4]
call :moveobject my.array[2] my.array[5]
call :moveobject my.array[3] my.array[6]

echo.&echo Printing my.array&echo.
REM call :echoarray my.array LINENUMBERS
echo.&call :echoarray my.array .suffixA LINENUMBERS

GoTo :EOF
Here is the output of that

Code: Select all

MoveObject-DEMO.bat

Printing my.array


0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:test.sufA.6
7:test.sufA.7

Moving object [6] to [4]

my.array[6] , my.array[6].suffixA , test.sufA.6 , .suffixA
new variable is my.array[6].suffixA
set command should be set my.array[6].suffixA=test.sufA.6

Printing my.array


0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:
7:test.sufA.7

Moving object [4] to [3]

my.array[4] , my.array[4].array[6] , test.sufA.6 , .array[6]
new variable is my.array[4].array[6]
set command should be set my.array[4].array[6]=test.sufA.6

Printing my.array


0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:
7:test.sufA.7

Moving objects [1][2][3] to [4][5][6]

my.array[1] , my.array[1].suffixA , test.sufA.1 , .suffixA
new variable is my.array[1].suffixA
set command should be set my.array[1].suffixA=test.sufA.1
my.array[2] , my.array[2].suffixA , test.sufA.2 , .suffixA
new variable is my.array[2].suffixA
set command should be set my.array[2].suffixA=test.sufA.2
my.array[3] , my.array[3].array[4] , test.sufA.6 , .array[4]
new variable is my.array[3].array[4]
set command should be set my.array[3].array[4]=test.sufA.6

Printing my.array


0:test.sufA.0
1:
2:
3:
4:
5:
6:
7:test.sufA.7


The important bit are

my.array[6] , my.array[6].suffixA , test.sufA.6 , .suffixA
new variable is my.array[6].suffixA
set command should be set my.array[6].suffixA=test.sufA.6

my.array[4] , my.array[4].array[6] , test.sufA.6 , .array[6]
new variable is my.array[4].array[6]
set command should be set my.array[4].array[6]=test.sufA.6

my.array[1] , my.array[1].suffixA , test.sufA.1 , .suffixA
new variable is my.array[1].suffixA
set command should be set my.array[1].suffixA=test.sufA.1

my.array[2] , my.array[2].suffixA , test.sufA.2 , .suffixA
new variable is my.array[2].suffixA
set command should be set my.array[2].suffixA=test.sufA.2

my.array[3] , my.array[3].array[4] , test.sufA.6 , .array[4]
new variable is my.array[3].array[4]
set command should be set my.array[3].array[4]=test.sufA.6


Based on that I made the new version of :MoveObject

Code: Select all

:MoveObject
set _MoveObject_Input=%~1
for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" EQU "[%~1]" set %~2=%%b
for /f "tokens=1,2* delims==" %%a in ('set %~1. 2^>nul') do  (
	setlocal enabledelayedexpansion
	set _var_name_buffer=%%a
	set _var_name_remain_buffer=!_var_name_buffer:%_MoveObject_Input%=!
	set _var_set_command=set %_MoveObject_Input%!_var_name_remain_buffer!=
	endlocal & %_var_set_command%%%b
	)
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1 2^>nul') do set %%a=
GoTo :EOF
There is just one problem, the %_var_set_command% macro expands to nothing inside a for loop but outside of enabledelayedexpansion !

Here is the latest version of this file, this one really doesn't work
MoveObject-DEMO.zip
(3.11 KiB) Downloaded 102 times

shodan
Posts: 54
Joined: 01 May 2023 01:49

Re: :MoveObject :MoveArray quick function to move array element and objects

#5 Post by shodan » 16 Sep 2023 17:08

I have created a new version of :MoveObject to address the problem in the previous version

This version appears to work and passes the DEMO function

Here is the new function

:MoveObject

Code: Select all

:MoveObject
set "_MoveObject_prefix=_MO"
set _MO_Input=%~1
set _MO_Output=%~2

REM this copies the variable only
for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" EQU "[%~1]" set %~2=%%b

setlocal enabledelayedexpansion
set _MO_localscope=true
set /a "_MO_Suffix_buffer.ubound=-1"

REM this should copy all variable suffix to the new destination
for /f "tokens=1,2* delims==" %%a in ('set %~1. 2^>nul') do  (
	set _MO_Suffix_buffer=%%a
	if "[!_MO_Suffix_buffer:%_MO_Input%=!]" NEQ "[]" (
		set /a "_MO_Suffix_buffer.ubound+=1"
		set "_MO_Suffix_buffer[!_MO_Suffix_buffer.ubound!].input=%%a
		set "_MO_Suffix_buffer[!_MO_Suffix_buffer.ubound!].output=%_MO_Output%!_MO_Suffix_buffer:%_MO_Input%=!"
		REM echo %_MO_Input% , %%a , %_MO_Output%!_MO_Suffix_buffer:%_MO_Input%=!
		)
	)

REM echo _MO_Input %_MO_Input%
REM set _MO_Suffix_buffer[

REM for each element in the suffix buffer, copy that element to the new root variable
for /l %%a in (0,1,%_MO_Suffix_buffer.ubound%) do (
	set _MO_Output_input_buffer=!_MO_Suffix_buffer[%%a].input!
	set _MO_Output_output_buffer=!_MO_Suffix_buffer[%%a].output!
	for /f "tokens=*" %%Z in ('echo.!_MO_Output_output_buffer!') do for /f "tokens=1,2* delims==" %%a in ('set !_MO_Output_input_buffer! 2^>nul') do (
										endlocal 
										set %%Z=%%b
										)
										
	
	)
if defined _MO_localscope endlocal

REM this clears the old base variable
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1 2^>nul') do set %%a=
Call :ClearVariablesByPrefix %_MoveObject_prefix% _MoveObject 
GoTo :EOF
This version lacks optimisation to skip the object copying portion if there are none.

Here is the output of the DEMO function, showing this now works with the .suffix as intended

Code: Select all

MoveObject-DEMO.bat

Printing my.array


0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:test.sufA.6
7:test.sufA.7

Moving object [6] to [4]


Printing my.array


0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:test.sufA.6
5:
6:
7:test.sufA.7

Moving object [4] to [3]


Printing my.array


0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:test.sufA.6
4:
5:
6:
7:test.sufA.7

Moving objects [1][2][3] to [4][5][6]


Printing my.array


0:test.sufA.0
1:
2:
3:
4:test.sufA.1
5:test.sufA.2
6:test.sufA.6
7:test.sufA.7


Here is the Full version of the DEMO code, included the base array elements shown

Code: Select all

MoveObject-DEMO.bat

Printing my.array

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:
5:
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:test.sufA.6
7:test.sufA.7

Moving object [6] to [4]


Printing my.array

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:Create, edit, copy, move, download your files easily,
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:test.sufA.6
5:
6:
7:test.sufA.7

Moving object [4] to [3]


Printing my.array

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:Create, edit, copy, move, download your files easily,
4:
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:test.sufA.6
4:
5:
6:
7:test.sufA.7

Moving objects [1][2][3] to [4][5][6]


Printing my.array

0:Open Source, light and extremely simple,
1:
2:
3:
4:It is a single executable file with no dependencies.
5:Just download it and add it to your PATH
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:
2:
3:
4:test.sufA.1
5:test.sufA.2
6:test.sufA.6
7:test.sufA.7


Here is the full file as run in the above output
MoveObject-DEMO.zip
(3.43 KiB) Downloaded 94 times

shodan
Posts: 54
Joined: 01 May 2023 01:49

Re: :MoveObject :MoveArray quick function to move array element and objects

#6 Post by shodan » 16 Sep 2023 17:16

Here is a new version that will skip the object copying code in the middle if no suffix is found

This version also passes the test, this version works for my current purpose until I find something that breaks it !

:MoveObject

Code: Select all

:MoveObject
set "_MoveObject_prefix=_MO"
set _MO_Input=%~1
set _MO_Output=%~2

REM this copies the variable only
for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" EQU "[%_MO_Input%]" set %~2=%%b

for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" NEQ "[%_MO_Input%]" GoTo :MoveObject-goto-skip
GoTo :MoveObject-object-skip
:MoveObject-goto-skip

setlocal enabledelayedexpansion
set _MO_localscope=true
set /a "_MO_Suffix_buffer.ubound=-1"

REM this should copy all variable suffix to the new destination
for /f "tokens=1,2* delims==" %%a in ('set %~1. 2^>nul') do  (
	set _MO_Suffix_buffer=%%a
	if "[!_MO_Suffix_buffer:%_MO_Input%=!]" NEQ "[]" (
		set /a "_MO_Suffix_buffer.ubound+=1"
		set "_MO_Suffix_buffer[!_MO_Suffix_buffer.ubound!].input=%%a
		set "_MO_Suffix_buffer[!_MO_Suffix_buffer.ubound!].output=%_MO_Output%!_MO_Suffix_buffer:%_MO_Input%=!"
		)
	)

REM for each element in the suffix buffer, copy that element to the new root variable
for /l %%a in (0,1,%_MO_Suffix_buffer.ubound%) do (
	set _MO_Output_input_buffer=!_MO_Suffix_buffer[%%a].input!
	set _MO_Output_output_buffer=!_MO_Suffix_buffer[%%a].output!
	for /f "tokens=*" %%Z in ('echo.!_MO_Output_output_buffer!') do for /f "tokens=1,2* delims==" %%a in ('set !_MO_Output_input_buffer! 2^>nul') do (
										endlocal 
										set %%Z=%%b
										)
	)
if defined _MO_localscope endlocal

:MoveObject-object-skip

REM this clears the old base variable
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1 2^>nul') do set %%a=
Call :ClearVariablesByPrefix %_MoveObject_prefix% _MoveObject 
GoTo :EOF

Latest copy of the demo file
MoveObject-DEMO.zip
(3.44 KiB) Downloaded 97 times

shodan
Posts: 54
Joined: 01 May 2023 01:49

Re: :MoveObject :MoveArray quick function to move array element and objects

#7 Post by shodan » 16 Sep 2023 17:57

I have created a more efficient and compact version of :MoveObject

This gets rid of the buffer array.

One frustrating thing I have discovered, if you have an IF branch inside a FOR loop, for some reason if I tried to do a variable substitution inside the for loop to one of those variables, it would not work.
I resolved this by doing the substitution before entering the IF. Very strange !

:MoveObject

Code: Select all

:MoveObject
set "_MoveObject_prefix=_MO"
set _MO_Input=%~1
set _MO_Output=%~2

REM this copies the variable only
for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" EQU "[%_MO_Input%]" set %~2=%%b

for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" NEQ "[%_MO_Input%]" GoTo :MoveObject-goto-skip
GoTo :MoveObject-object-skip
:MoveObject-goto-skip

setlocal enabledelayedexpansion
set _MO_localscope=true

REM this should copy all variable suffix to the new destination
for /f "tokens=1,2* delims==" %%a in ('set %~1. 2^>nul') do  (
	set _MO_Suffix_buffer_input=%%a
	set _MO_Suffix_buffer_output=%_MO_Output%!_MO_Suffix_buffer_input:%_MO_Input%=!
	if "[!_MO_Suffix_buffer_input:%_MO_Input%=!]" NEQ "[]" (
		for /f "tokens=*" %%Z in ('echo.!_MO_Suffix_buffer_output!') do (
																	endlocal 
																	set %%Z=%%b
																	)
		)
	)
if defined _MO_localscope endlocal
:MoveObject-object-skip

REM this clears the old base variable
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1 2^>nul') do set %%a=
Call :ClearVariablesByPrefix %_MoveObject_prefix% _MoveObject 
GoTo :EOF
Here is the output
It works

Code: Select all

MoveObject-DEMO.bat

Printing my.array

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:
5:
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:test.sufA.6
7:test.sufA.7

Moving object [6] to [4]


Printing my.array

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:Create, edit, copy, move, download your files easily,
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:test.sufA.6
5:
6:
7:test.sufA.7

Moving object [4] to [3]


Printing my.array

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:Create, edit, copy, move, download your files easily,
4:
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:test.sufA.6
4:
5:
6:
7:test.sufA.7

Moving objects [1][2][3] to [4][5][6]


Printing my.array

0:Open Source, light and extremely simple,
1:
2:
3:
4:It is a single executable file with no dependencies.
5:Just download it and add it to your PATH
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:
2:
3:
4:test.sufA.1
5:test.sufA.2
6:test.sufA.6
7:test.sufA.7

Here is the alternative which triggers the problem

DON'T USE

Code: Select all

:MoveObject
set "_MoveObject_prefix=_MO"
set _MO_Input=%~1
set _MO_Output=%~2

REM this copies the variable only
for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" EQU "[%_MO_Input%]" set %~2=%%b

for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do if "[%%a]" NEQ "[%_MO_Input%]" GoTo :MoveObject-goto-skip
GoTo :MoveObject-object-skip
:MoveObject-goto-skip

setlocal enabledelayedexpansion
set _MO_localscope=true

REM this should copy all variable suffix to the new destination
for /f "tokens=1,2* delims==" %%a in ('set %~1. 2^>nul') do  (
	set _MO_Suffix_buffer_input=%%a
	REM set _MO_Suffix_buffer_output=%_MO_Output%!_MO_Suffix_buffer_input:%_MO_Input%=!
	if "[!_MO_Suffix_buffer_input:%_MO_Input%=!]" NEQ "[]" (
		for /f "tokens=*" %%Z in ('echo.%_MO_Output%!_MO_Suffix_buffer_input:%_MO_Input%=!') do (
																	endlocal 
																	set %%Z=%%b
																	)
		)
	)
if defined _MO_localscope endlocal
:MoveObject-object-skip

REM this clears the old base variable
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1 2^>nul') do set %%a=
Call :ClearVariablesByPrefix %_MoveObject_prefix% _MoveObject 
GoTo :EOF

So, this line works

Code: Select all

for /f "tokens=*" %%Z in ('echo.!_MO_Suffix_buffer_output!') do (
but this one doesn't, and I don't really understand why. This is because of the IF branch very likely ... but I don't get it

Code: Select all

for /f "tokens=*" %%Z in ('echo.%_MO_Output%!_MO_Suffix_buffer_input:%_MO_Input%=!') do (
Here is the content of the my.array after running the broken line

Code: Select all

set my
my.array.ubound=7
my.array[0]=Open Source, light and extremely simple,
my.array[0].suffixA=test.sufA.0
my.array[4]=It is a single executable file with no dependencies.
my.array[4]_MO_Suffix_buffer_input:my.array[1] =test.sufA.1
my.array[5]=Just download it and add it to your PATH
my.array[5]_MO_Suffix_buffer_input:my.array[2] =test.sufA.2
my.array[6]=Create, edit, copy, move, download your files easily,
my.array[7]=everywhere, every time. Use it as your personal cloud.
my.array[7].suffixA=test.sufA.7
If I add to the for loop, the debug output as follows

Code: Select all

echo set %%Z=%%b

Here is this output from running the DEMO

Code: Select all

set my.array[4]_MO_Suffix_buffer_input:my.array[6] =test.sufA.6
set my.array[4]_MO_Suffix_buffer_input:my.array[1] =test.sufA.1
set my.array[5]_MO_Suffix_buffer_input:my.array[2] =test.sufA.2
I don't understand why the substitution breaks but not the plain variable expansion ?


Here is the current version including
This version is still working and improved compared with the last one
MoveObject-DEMO.zip
(3.57 KiB) Downloaded 98 times

shodan
Posts: 54
Joined: 01 May 2023 01:49

Re: :MoveObject :MoveArray quick function to move array element and objects

#8 Post by shodan » 16 Sep 2023 19:37

The previous very, I believe would only copy one suffix element from the object, then go out of scope with the endlocal


I retooled :MoveObject to be more compact and as a bonus now it will move all .suffix from an object like my.array[28].suffixB

:MoveObject

Code: Select all

:MoveObject
set "_MoveObject_prefix=_MO"
set _MO_Input=%~1
set _MO_Output=%~2

REM this should copy all variable suffix to the new destination
for /f "tokens=1,2* delims==" %%a in ('set %~1 2^>nul') do  (
	setlocal enabledelayedexpansion
	set _MO_Suffix_buffer_input=%%a
	set _MO_Suffix_buffer_output=%_MO_Output%!_MO_Suffix_buffer_input:%_MO_Input%=!
	for /f "tokens=*" %%Z in ('echo.!_MO_Suffix_buffer_output!') do (
																endlocal 
																set %%Z=%%b
																)
	)
if defined _MO_localscope endlocal

REM this clears the old base variable
if "[%~1]" NEQ "[]" for /f "tokens=1,2 delims==" %%a in ('set %~1 2^>nul') do set %%a=
Call :ClearVariablesByPrefix %_MoveObject_prefix% _MoveObject 
GoTo :EOF
I have create a new version of the DEMO function which now has a base element variable and two .suffix, .suffixA and .suffixB

Code: Select all

:MoveObject-DEMO3
set myarray[0]=Open Source, light and extremely simple,
set myarray[1]=It is a single executable file with no dependencies.
set myarray[2]=Just download it and add it to your PATH
set myarray[6]=Create, edit, copy, move, download your files easily,
set myarray[7]=everywhere, every time. Use it as your personal cloud.
set myarray[0].suffixA=test.sufA.0
set myarray[1].suffixA=test.sufA.1
set myarray[2].suffixA=test.sufA.2
set myarray[6].suffixA=test.sufA.6
set myarray[7].suffixA=test.sufA.7
set myarray[0].suffixB=test.sufB.0
set myarray[1].suffixB=test.sufB.1
set myarray[2].suffixB=test.sufB.2
set myarray[6].suffixB=test.sufB.6
set myarray[7].suffixB=test.sufB.7
set myarray.ubound=7

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
echo.&call :echoarray myarray .suffixA LINENUMBERS
echo.&call :echoarray myarray .suffixB LINENUMBERS

echo.&echo Moving object [6] to [4]&echo.
call :moveobject myarray[6] myarray[4]

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
echo.&call :echoarray myarray .suffixA LINENUMBERS
echo.&call :echoarray myarray .suffixB LINENUMBERS

echo.&echo Moving object [4] to [3]&echo.
call :moveobject myarray[4] myarray[3]

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
echo.&call :echoarray myarray .suffixA LINENUMBERS
echo.&call :echoarray myarray .suffixB LINENUMBERS

echo.&echo Moving objects [1][2][3] to [4][5][6]&echo.
call :moveobject myarray[1] myarray[4]
call :moveobject myarray[2] myarray[5]
call :moveobject myarray[3] myarray[6]

echo.&echo Printing myarray&echo.
call :echoarray myarray LINENUMBERS
echo.&call :echoarray myarray .suffixA LINENUMBERS
echo.&call :echoarray myarray .suffixB LINENUMBERS

GoTo :EOF
Here is the output to that DEMO function

Code: Select all

MoveObject-DEMO.bat

Printing myarray

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:
5:
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:
5:
6:test.sufA.6
7:test.sufA.7

0:test.sufB.0
1:test.sufB.1
2:test.sufB.2
3:
4:
5:
6:test.sufB.6
7:test.sufB.7

Moving object [6] to [4]


Printing myarray

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:
4:Create, edit, copy, move, download your files easily,
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:
4:test.sufA.6
5:
6:
7:test.sufA.7

0:test.sufB.0
1:test.sufB.1
2:test.sufB.2
3:
4:test.sufB.6
5:
6:
7:test.sufB.7

Moving object [4] to [3]


Printing myarray

0:Open Source, light and extremely simple,
1:It is a single executable file with no dependencies.
2:Just download it and add it to your PATH
3:Create, edit, copy, move, download your files easily,
4:
5:
6:
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:test.sufA.1
2:test.sufA.2
3:test.sufA.6
4:
5:
6:
7:test.sufA.7

0:test.sufB.0
1:test.sufB.1
2:test.sufB.2
3:test.sufB.6
4:
5:
6:
7:test.sufB.7

Moving objects [1][2][3] to [4][5][6]


Printing myarray

0:Open Source, light and extremely simple,
1:
2:
3:
4:It is a single executable file with no dependencies.
5:Just download it and add it to your PATH
6:Create, edit, copy, move, download your files easily,
7:everywhere, every time. Use it as your personal cloud.

0:test.sufA.0
1:
2:
3:
4:test.sufA.1
5:test.sufA.2
6:test.sufA.6
7:test.sufA.7

0:test.sufB.0
1:
2:
3:
4:test.sufB.1
5:test.sufB.2
6:test.sufB.6
7:test.sufB.7
And here is the whole file as it exists now
This might be the final working version of :MoveObject
Attachments
MoveObject-DEMO.zip
(3.62 KiB) Downloaded 91 times

Post Reply