Batch: Parsing out file path from dynamic array [duplicate] - arrays

This question already has an answer here:
Batch recursing through folders & populating an array
(1 answer)
Closed 6 years ago.
Looking to parse out the path from a specific point & then use that to populate the dynamic array.
Example:
Folder tree:
C:\Main\folder1
C:\Main\folder2\folder2-1
C:\Main\folder3\folder3-1\folder3-2
Desired result:
Array[1]=folder1
Array[2]=folder2
Array[3]=folder2\folder2-1
Array[4]=folder3
Array[5]=folder3\folder3-1\
Array[6]=folder3\folder3-1\folder3-2
This is the working code below which returns fine but in full paths:
#echo off
setlocal EnableDelayedExpansion
SET folders=C:\Main
rem Populate the array with existent files in folder
set i=0
for /r "%folders%" /d %%a in (*) do (
set /A i+=1
set list[!i!]=%%a
)
set foldnum=%i%
rem Display array elements
for /L %%i in (1,1,%foldnum%) do (SET array[%%i]=!list[%%i]!)
for /F "tokens=2 delims==" %%f in ('set array[') do echo %%f

You pass an absolute path to the FOR loop. But even with a relative path the FOR loop does too much and converts it to an absolute path.
The trick here is to replace the absolute path in the FOR loop.
Create a copy of the loop variable in a real variable
set AA=%%a
Then replace prefix+backslash by nothing in the list "array'
set list[!i!]=!AA:%folders%\=!
full fixed code:
#echo off
setlocal EnableDelayedExpansion
SET folders=C:\Main
rem Populate the array with existent files in folder
set i=0
for /r "%folders%" /d %%a in (*) do (
set /A i+=1
rem create a copy of the loop variable in a real variable
set AA=%%a
rem replace prefix+backslash by nothing in a the list "array"
set list[!i!]=!AA:%folders%\=!
)
set foldnum=%i%
rem Display array elements
for /L %%i in (1,1,%foldnum%) do (SET array[%%i]=!list[%%i]!)
for /F "tokens=2 delims==" %%f in ('set array[') do echo %%f
then you get all the dirs of %folders% in a relative way.

A little bit of Tom Foolery.
#echo off
setlocal EnableDelayedExpansion
SET folders=C:\Main
subst B: %folders%
B:
set i=0
for /r /d %%G in (*) do (
set /A i+=1
FOR /F "tokens=* delims=\" %%H IN ("%%~pnG") do set "array[!i!]=%%~H"
)
C:
subst B: /D
set foldnum=%i%
rem Display array elements
for /F "tokens=2 delims==" %%f in ('set array[') do echo %%f
pause

Related

pass outer loop variable into nested loop

So my mission is to loop through a directory and set a variable to capture the zip file name.
then use that variable to parse what is on the left of the string before the underscore. That way I can name a log file. I searched high and low but I'm not seeing any good examples on Stack. when I use %%i it will return a full directory path. (which is not needed here.) If I use the %%z I get null back how can I pass my %zipfile% variable into my nested loop In()?
setlocal enableextensions enabledelayedexpansion
set dir1="C:\test\"
set 7zip="C:\Program Files\7-Zip\7z.exe"
set output="C:\test\Filelist.txt"
REM enter folder location
cd C:\test
REM loop through zip files
for /r %%i in (*.zip) do ( set zipfile=%%~nxi
for /F " delims=_" %%z in (%zipfile%) do (set log="%%z_file_list.txt")
)
Pause
REM Del %log%
Does the following help you out?
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "dir1=C:\test"
Set "7zip="%ProgramFiles%\7-Zip\7z.exe"
Set "output=C:\test\Filelist.txt"
For /F "Delims=" %%G In (
'Set "PATHEXT=" ^& %SystemRoot%\System32\where.exe /F /R "%dir1%" "?*_*.zip" 2^>NUL'
) Do (
For /F "Delims=_" %%H In (
"%%~nG"
) Do (
Echo Set "log=%%H_file_list.txt"
)
)
Pause

How to remove duplicate comma separated values from variable using batch file?

Want to remove the duplicate values from machines variable in below batch file:
#echo off
set machines=node1,node2,node3,node2,node4,node1,node7,node6,node4
Expected output:
node1,node2,node3,node4,node6,node7
One way to accomplish your task:
Iterate the machines with a for and set them to an array,
this overwrites doublette entries.
Read the (alpha sorted) array back and store in the original variable (requires delayed expansion).
:: Q:\Test\2018\09\20\SO_52417320.cmd
#Echo off & Setlocal EnableDelayedExpansion
Set machines=node1,node2,node3,node2,node4,node1,node7,node6,node4
:: clear array machine[], then fill it
For /f "tokens=1 delims==" %%M in ('Set machine[ 2^>Nul') do Set "%%M="
For %%M in (%machines%) do Set "machine[%%M]=%%M"
Set machine[
Echo:
Set "machines="
For /f "tokens=2 delims==" %%M in ('Set machine[') do Set "machines=!machines!,%%M"
Echo:%machines:~1%
Sample output:
> SO_52417320.cmd
machine[node1]=node1
machine[node2]=node2
machine[node3]=node3
machine[node4]=node4
machine[node6]=node6
machine[node7]=node7
node1,node2,node3,node4,node6,node7
A short way to do it (this doesn't sort the machines variable, only removes the duplicates):
#echo off& setlocal EnableDelayedExpansion
set machines=node1,node2,node3,node2,node4,node1,node7,node6,node4
set "tmac=,"& for %%a in (%machines%) do if "!tmac:,%%a,=!"=="!tmac!" set "tmac=!tmac!%%a,"
set machines=%tmac:~1,-1%

Parent directory batch

In a previous question of mine, Aacini provided me with this code:
#echo on
setlocal EnableDelayedExpansion
set "digits=8"
set mypath=%~dp0
cd /d "%~dp0"
rem delete old list from current even if read only
del /f list.txt
rem Assemble the factor with the proper number of digits
set "factor=1"
for /L %%i in (1,1,%digits%) do set "factor=!factor!0"
rem Accumulate size of all extensions in 2 groups of %digits% digits each
for %%a in (*.*) do (
set "size=%factor%%%~Za"
set /A "low[%%~Xa]+=1!size:~-%digits%!-factor, carry=low[%%~Xa]/factor,
low[%%~Xa]%%=factor"
set "size=%%~Za"
set "size=!size:~0,-%digits%!"
set /A "high[%%~Xa]+=carry+size"
)
rem Show results
for /F "tokens=2,3 delims=[.]=" %%a in ('set high[') do (
if %%b neq 0 (
set "low=%factor%!low[.%%a]!"
echo %%a %%b!low:~-%digits%! bytes >>"%mypath%\list.txt"
) else (
echo %%a !low[.%%a]! bytes >>"%mypath%\list.txt"
)
)
Now I'm trying to make it search through the parent directory when creating the list.
I still want the final test file to be saved to the local directory, so no changes there!

Batch: Checking if any variables are equal

Thanks to Aacini, I now have a way to sort variables from greatest to least.
Link:
Comparing and ordering multiple numbers in batch
However, if 2 or more of my variables are the same value, they won't be sorted. I'm trying test to see if two variables in the set are equal. I tried using if statements against each variable in any combination I could think of, but that isn't very efficient and is hard to change.
Is there a way I can achieve this?
#echo off
setlocal EnableDelayedExpansion
set speed1=190
set speed2=78
set speed3=78
set speed4=23
rem Get the descending order of previous elements via "order" array
for /L %%i in (1,1,4) do (
set /A num=1000-speed%%i
set order!num!=%%i
)
rem Show the elements of "speed" array in descending order
for /F "tokens=2 delims==" %%i in ('set order') do (
echo speed%%i = !speed%%i!
)
Output will only display:
speed1 = 190
speed3 = 78
speed4 = 23
Excuse me. I don't know if you are really interested to know if two elements have the same value, or just to fix the bug of my previous solution (that don't include the elements with the same value), so I opted for solve previous bug:
#echo off
setlocal EnableDelayedExpansion
set speed1=190
set speed2=78
set speed3=78
set speed4=23
rem Get the descending order of previous elements via "order" array
REM Insert a second index to differentiate elements with the same value
for /L %%i in (1,1,4) do (
set /A num=1000-speed%%i
set order[!num!][%%i]=%%i
)
rem Show the elements of "speed" array in descending order
for /F "tokens=2 delims==" %%i in ('set order') do (
echo speed%%i = !speed%%i!
)
#echo off
setlocal enableextensions enabledelayedexpansion
set speed1=190
set speed2=78
set speed3=78
set speed4=23
for /f "usebackq tokens=1,2 delims=/" %%a in (`
cmd /q /e /c "for /f tokens^=1^,2^ delims^=^= %%c in ('set speed') do (set /a %%d + 10000000 & echo /%%c)"
^| sort /r
`) do (
set /a "value=%%a-10000000"
echo %%b=!value!
)

Copy files from a file list to a folder list in batch

I have two text files...files.txt containing a list of filenames and dirs.txt containing the list of directories the files need to be copied to.
This is how the files need to be copied:
File 1 ------------------------> Folder 1
File 2 ------------------------> Folder 2
File 3 ------------------------> Folder 3
How do I implement this using batch? Thanks in advance...
Try this:
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in (files.txt) do (
set /p dir=
echo copy "%%~a" "!dir!"
)<dirs.txt
pause
The above works - Mona can revise or remove the following:
setlocal enabledelayedexpansion
3<dirs.txt(
for /f "delims=" %%a in (files.txt) do (
set /p dir=<&3
copy "%%~a" "!dir!"
)
)
And that should do what you want. Note if dirs.txt has less lines then files.txt, this will fail.
Mona.
Well I managed to figure it out...thanks to this answer from #foxidrive. Here is the code:
#echo off
setlocal enabledelayedexpansion
set /A i=0
for /F "usebackq delims==" %%a in (files.txt) do (
set /A i+=1
call set array1[%%i%%]=%%a
call set n=%%i%%
)
set /A i=0
for /F "usebackq delims==" %%a in (dirs.txt) do (
set /A i+=1
call set array2[%%i%%]=%%a
)
for /L %%i in (1,1,%n%) do call copy "%%array1[%%i]%%" "%%array2[%%i]%%"
It's definitely not the best solution...but it works!
Thanks everyone for your help.

Resources