I want to create a For loop to look if a program is on a flash drive, and copy a text file if it is. Since the drive letter varies on every PC, I want it to look at every drive letter.
if exist "D:\Test.exe" (
copy "%FileName%.txt" "D:\" >nul
)
if exist "E:\Test.exe" (
copy "%FileName%.txt" "E:\" >nul
)
if exist "F:\Test.exe" (
copy "%FileName%.txt" "F:\" >nul
)
if exist "G:\Test.exe" (
copy "%FileName%.txt" "G:\" >nul
)
Rem ...Continues possibly until drive Z or once it finds the file
Is there a way to create a For loop to increment the drive letter so I don't have to make an If statement each time?
Here is a community wiki with all methods combined from the comments, per user.
Squashman
#echo off
FOR %%G IN (A B C D etc..Z) DO IF EXIST "%%G:\test.exe" copy
then, a very intuitive method using the exit codes 65 to 90 in ascii format, by Aacini.
#echo off
setlocal enabledelayedexpansion
for /L %%i in (65,1,90) do cmd /C exit %%i & if exist "!=ExitCodeAscii!:\test.exe" copy...
Then my suggestion of using wmic to find all the actual drive letters available on the device:
#echo off
for /f "tokens=2*delims==" %%i in ('wmic logicaldisk get caption /value') do for /f "delims=" %%d in ("%%i") do if exist "%%d\test.exe" copy ...
Related
I have an unknown number of text files in a directory which are named as such, ABC1200f1234.EAU, but they are all slightly different. The internal structure of each text file is the same, but the contents are different. Within each file there is a string * SERIAL NUMBER:XXXXX *. For each file the 6 characters following the SERIAL NUMBER: is different. I am trying to search each file to obtain the 6 digits following SERIAL NUMBER: then move that file to a directory named after the 6 digits, e.g. if the 6 digits are A12345 then I want to create a directory named A12345 and move the file there, then move on to the next file until all files have been moved.
The following code gets the 6 digits into %%a but I'm stuck on how to then move the file, before moving onto the next one. I'm sure I'm just missing one small piece of the puzzle.
#ECHO OFF
CLS
cd c\Temp
setlocal enableextensions disabledelayedexpansions
set sourcedir=c:temp
set targetdir=c:\temp\parsed
for /f "tokens=4 delims=*:" %%a in (
'findstr /r "SERIAL NUMBER:" %sourcedir%\*'
) do (
if exists %targetdir%\%%a (
echo Directory already exists
) else mkdir %targerdir%\%%a
)
move %sourcedir%\%%a %targetdir%\%%a
)
I'm sure the last line is the problem because %%a now holds the 6 digit number, not the filename.
Please don't suggest Powershell as that is not an option. I also realise I can use robocopy and remove the check to see if the target directory exists.
Any help you can give would be most appreciated.
I'm assuming for this code that the serial number is directly after the colon with no white space or other characters whcih need to be removed before or after it.
#(setlocal EnableDelayedExpansion
ECHO OFF
CLS
set "sourcedir=c:\temp"
set "targetdir=c:\temp\parsed"
SET "FileGlob=*.EAU"
)
CALL :Main
( Endlocal
EXIT /B
)
:Main
FOR %%_ IN (
"%sourcedir%\%FileGlob%"
) DO (
Echo=processing "%%~_"
FOR /F "Tokens=2 delims=:" %%F IN ('
TYPE "%%~_" ^| FIND /I "SERIAL NUMBER:"
') DO (
ECHO=Found. Serial number "%%F" trimmingbany spaces
FOR /F "Tokens=*" %%f IN ("%%~F") DO (
ECHO=Trimmed serial number "%%~f" stored
SET "_TmpFolder=%%F"
)
)
MD "%TargetDir%\!_TmpFolder!\"
MOVE "%%~_" "%TargetDir%\!_TmpFolder!\%%~nx_"
)
GOTO :EOF
There is not any need to test if the directory you're trying to create exists. Simply do mkdir and pipe the output to nul
NOTE! This example assumes that the Serial Number is on it's own line in the file, seeing as you have not shown an actual example of your text file.
#echo off
set "source=c:\temp"
set "target=c:\temp\parsed"
for %%a in ("%source%\*.EAU") do for /f "tokens=2* delims=:" %%i in ('type "%%~a" ^|findstr /i "serial number"') do (
mkdir "%target%\%%i">nul 2>&1
move "%%~a" "%target%\%%i"
)
As far as overwriting existing files are concerned, that is something you need to decide as I do not know your exact scenario, so did not include additional parameters to the move command.
I wrote this batch script so that it can go through each folder and tell me how many files in this folder but I only want it to apply to a certain drive how would I write this?`do I add it right after #echo off? also how do you write the path for the drive (i.e. if my drive is name lets say "adrive" under the Y: how would I write it if that makes sense)
#echo off
title File Counter batch.
:recurse
set I=1
echo "files in folder"
cd
REM view all files, EXCEPT directories.
FOR /f "tokens=*" %%P IN ('dir /A-d /b') do (call :showfiles "%%P")
echo Filecount: %I%
REM now call on all subfolders...
pause
:showfiles
echo %1
set /a I+=1
goto :eof`
If I understand you correctly, you want to know how many files are in each folder of a certain drive. That's quite easy: for /d /r lists you recursively each folder. Use a second for /f loop to count the files for each folder:
#echo off
setlocal
set sum=0
for /d /r "Y:\" %%a in (*) do (
for /f %%b in ('dir /b /a-d "%%a\*" 2^>nul ^|find /c /v ""') do (
echo %%b %%a
set /a sum+=%%b
)
)
echo sum=%sum%
NOTE: this counts non-hidden, non-system files only. Adapt the dir switches to change that when needed.
I'm trying to list non-symbolic links in an specific directory and then delete them.
non-symbolic links definition: any file besides the ones that have been created using the command MKLINK /H
To identify those non-symbolic links I used the following approach:
#> fsutil hardlink list %file% | find /c /v ""
When the specified %file% is a symbolic link it returns a number bigger than 1, when it is just a simple file, it returns 1. So far so good!
My problem starts when I need to automate this process and get such return to compare if it is bigger than 1
That's is the code I'm trying to get running property:
#echo off
set some_dir=C:\TEMP\
for /f %%a in ('dir /b %some_dir%') do (
set count=fsutil hardlink list %%a | find /c /v ""
if %count% -EQU 1 del /Q %%a
)
Would someone explain me how such attribution and comparison on %count% variable could be done, please?
I'm trying to list non-symbolic links in an specific directory and then delete them.
There are some issues with your code.
for /f %%a in ('dir /b %some_dir%') do (
The dir /b doesn't work because it doesn't return a file name with a complete path (which is required as input for fsutil)
Use dir /b /s instead.
set count=fsutil hardlink list %%a | find /c /v ""
This doesn't set count to anything sensible.
Use another for /f and parse the output of fsutil so you can set a variable.
if %count% -EQU 1 del /Q %%a
This has two mistakes. You need to use delayed expansion to evaluate count correctly. Replace %count% with !count!. Also remove the -. Replace -EQU with EQU.
Try the following batch file.
test.cmd:
#echo off
setlocal enabledelayedexpansion
set some_dir=C:\TEMP\
for /f %%a in ('dir /b /s %some_dir%') do (
for /f %%b in ('fsutil hardlink list %%a ^| find /c /v ""') do (
set count=%%b
if !count! EQU 1 echo del /Q %%a
)
)
endlocal
Notes:
Remove the echo when you happy with what the result will be.
Example usage and output:
I have used f:\test\folder1 as my test directory. hard is a hardlink to 1.txt.
F:\test>dir f:\test\folder1
Volume in drive F is Expansion
Volume Serial Number is 3656-BB63
Directory of f:\test\folder1
29/08/2016 21:40 <DIR> .
29/08/2016 21:40 <DIR> ..
21/08/2016 09:46 0 1.txt
21/08/2016 09:46 0 2.txt
21/08/2016 09:46 0 3.txt
21/08/2016 09:46 0 4.txt
21/08/2016 09:46 0 5.txt
29/08/2016 21:38 <SYMLINK> file [f:\d]
21/08/2016 09:46 0 hard
29/08/2016 21:38 <SYMLINKD> test [f:\d]
7 File(s) 0 bytes
3 Dir(s) 1,764,846,960,640 bytes free
F:\test>test
del /Q f:\test\folder1\2.txt
del /Q f:\test\folder1\3.txt
del /Q f:\test\folder1\4.txt
del /Q f:\test\folder1\5.txt
del /Q f:\test\folder1\file
del /Q f:\test\folder1\test
Further Reading
An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
dir - Display a list of files and subfolders.
enabledelayedexpansion - Delayed Expansion will cause variables to be expanded at execution time rather than at parse time.
for /f - Loop command against the results of another command.
There are some problems in your code:
you need delayed expansion because you are setting (writing) and expanding (reading) the variable count within the same parenthesised block of code (namely the for /F %%a loop);
in your for /F %%a loop you need to state options "eol=| delims=" in order not to run into trouble with files whose names begin with ; (such would be ignored due to the default eol=; option) and those which have white-spaces in their names (you would receive only the postion before the first white-space because of the default delims SPACE and TAB and the default option tokens=1 (see for /? for details about that);
dir /B returns file names only, so %%a actually points to files in the current directory rather than to C:\TEMP\; to fix that, simply change to that directory first by cd;
to capture the output of a command (line) and assign it to a variable, use another for /F loop and set; this loop is going to iterate once only, because find /C returns only a single line; note the escaped pipe ^| below, which is required to not execute it immediately;
there is no comparison operator -EQU, you need to remove the - to check for equality;
it is a good idea to use the quoted set syntax as it is most robust against poisonous characters;
file and directory paths should generally be quoted since they might contain token delimiters or other poisonous characters;
Here is the fixed script:
#echo off
setlocal EnableDelayedExpansion
pushd "C:\TEMP\" || exit /B 1
for /F "eol=| delims=" %%a in ('dir /B "."') do (
for /F %%b in ('
fsutil hardlink list "%%a" ^| find /C /V ""
') do (
set "count=%%b"
)
if !count! EQU 1 del "%%a"
)
popd
endlocal
This can even be simplified:
#echo off
pushd "C:\TEMP\" || exit /B 1
for /F "eol=| delims=" %%a in ('dir /B "."') do (
for /F %%b in ('
fsutil hardlink list "%%a" ^| find /C /V ""
') do (
if %%b EQU 1 del "%%a"
)
)
popd
Since the inner for /F loop iterates always once only, we can move the if query inside, thus avoiding the definition of an auxiliary variable which is the only one we needed delayed expansion for.
Simplified method:
#Echo Off
PushD X:\YourDirectory
For %%a In (*.*) Do (
FSUtil HardLink List %%a|FindStr/VIC:"%%~pnxa">Nul||(Echo=Del "%%~a"))
Pause
When you're satisfied with the output Remove line 5 and also 'Echo=' from line 4
I want to create a .bat script to copy only one random file from each folder (also subfolders, so recursively) whilst also keeping the folder structure. I've tried the following code which comes close to what I want but doesn't copy the folder structure and one file per folder.
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
SET Destination=H:\Temp
SET FileFilter=.ape
SET SubDirectories=/S
SET Source=%~dp1
SET FileList1Name=FileList1.%RANDOM%.txt
SET FileList1="%TEMP%\%FileList1Name%"
SET FileList2="%TEMP%\FileList2.%RANDOM%.txt"
ECHO Source: %Source%
IF /I {%SubDirectories%}=={/S} ECHO + Sub-Directories
IF NOT {"%FileFilter%"}=={""} ECHO File Filter: %FileFilter%
ECHO.
ECHO Destination: %Destination%
ECHO.
ECHO.
ECHO Building file list...
CD /D "%Source%"
DIR %FileFilter% /A:-D-H-S /B %SubDirectories% > %FileList1%
FOR /F "tokens=1,2,3 delims=:" %%A IN ('FIND /C ":" %FileList1%') DO SET TotalFiles=%%C
SET TotalFiles=%TotalFiles:~1%
ECHO The source has %TotalFiles% total files.
ECHO Enter the number of random files to copy to the destination.
SET /P FilesToCopy=
ECHO.
IF /I %TotalFiles% LSS %FilesToCopy% SET %FilesToCopy%=%TotalFiles%
SET Destination="%Destination%"
IF NOT EXIST %Destination% MKDIR %Destination%
SET ProgressTitle=Copying Random Files...
FOR /L %%A IN (1,1,%FilesToCopy%) DO (
TITLE %ProgressTitle% %%A / %FilesToCopy%
REM Pick a random file.
SET /A RandomLine=!RANDOM! %% !TotalFiles!
REM Go to the random file's line.
SET Line=0
FOR /F "usebackq tokens=*" %%F IN (%FileList1%) DO (
IF !Line!==!RandomLine! (
REM Found the line. Copy the file to the destination.
XCOPY /V /Y "%%F" %Destination%
) ELSE (
REM Not the random file, build the new list without this file included.
ECHO %%F>> %FileList2%
)
SET /A Line=!Line! + 1
)
SET /A TotalFiles=!TotalFiles! - 1
REM Update the master file list with the new list without the last file.
DEL /F /Q %FileList1%
RENAME %FileList2% %FileList1Name%
)
IF EXIST %FileList1% DEL /F /Q %FileList1%
IF EXIST %FileList2% DEL /F /Q %FileList2%
ENDLOCAL
The destination should be set in the .bat code like the code above. Can anybody please help me with this? Thanks in advance!
Copying a directory tree structure (folders only) is trivial with XCOPY.
Selecting a random file from a given folder is not too difficult. First you need the count of files, using DIR /B to list them and FIND /C to count them. Then use the modulo operator to select a random number in the range. Finally use DIR /B to list them again, FINDSTR /N to number them, and another FINDSTR to select the Nth file.
Perhaps the trickiest bit is dealing with relative paths. FOR /R can walk a directory tree, but it provides a full absolute path, which is great for the source, but doesn't do any good when trying to specify the destination.
There are a few things you could do. You can get the string length of the root source path, and then use substring operations to derive the relative path. See How do you get the string length in a batch file? for methods to compute string length.
Another option is to use FORFILES to walk the source tree and get relative paths directly, but it is extremely slow.
But perhaps the simplest solution is to map unused drive letters to the root of your source and destination folders. This enables you to use the absolute paths directly (after removing the drive letter). This is the option I chose. The only negative aspect of this solution is you must know two unused drive letters for your system, so the script cannot be simply copied from one system to another. I suppose you could programatically
discover unused drive letters, but I didn't bother.
Note: It is critical that the source tree does not contain the destination
#echo off
setlocal
:: Define source and destination
set "source=c:\mySource"
set "destination=c:\test2\myDestination"
:: Replicate empty directory structure
xcopy /s /t /e /i "%source%" "%destination%"
:: Map unused drive letters to source and destination. Change letters as needed
subst y: "%source%"
subst z: "%destination%"
:: Walk the source tree, calling :processFolder for each directory.
for /r y:\ %%D in (.) do call :processFolder "%%~fD"
:: Cleanup and exit
subst y: /d
subst z: /d
exit /b
:processFolder
:: Count the files
for /f %%N in ('dir /a-d /b %1 2^>nul^|find /c /v ""') do set "cnt=%%N"
:: Nothing to do if folder is empty
if %cnt% equ 0 exit /b
:: Select a random number within the range
set /a N=%random% %% cnt + 1
:: copy the Nth file
for /f "delims=: tokens=2" %%F in (
'dir /a-d /b %1^|findstr /n .^|findstr "^%N%:"'
) do copy "%%D\%%F" "z:%%~pnxD" >nul
exit /b
EDIT
I fixed an obscure bug in the above code. The original COPY line read as follows:
copy "%%~1\%%F" "z:%%~pnx1" >nul
That version fails if any of the folders within the source tree contain %D or %F in their name. This type of problem always exists within a FOR loop if you expand a variable with %var% or expand a :subroutine parameter with %1.
The problem is easily fixed by using %%D instead of %1. It is counter-intuitive, but FOR variables are global in scope as long as any FOR loop is currently active. The %%D is inaccessible throughout most of the :processFolder routine, but it is available within the FOR loops.
The "natural" way to process a directory tree is via a recursive subroutine; this method minimize the problems inherent to this process. As I said at this post: "You may write a recursive algorithm in Batch that gives you exact control of what you do in every nested subdirectory". I taken the code at this answer, that duplicate a tree, and slightly modified it in order to solve this problem.
#echo off
setlocal
set "Destination=H:\Temp"
set "FileFilter=*.ape"
rem Enter to source folder and process it
cd /D "%~dp1"
call :processFolder
goto :EOF
:processFolder
setlocal EnableDelayedExpansion
rem For each folder in this level
for /D %%a in (*) do (
rem Enter into it, process it and go back to original
cd "%%a"
set "Destination=%Destination%\%%a"
if not exist "!Destination!" md "!Destination!"
rem Get the files in this folder and copy a random one
set "n=0"
for %%b in (%FileFilter%) do (
set /A n+=1
set "file[!n!]=%%b"
)
if !n! gtr 0 (
set /A "rnd=!random! %% n + 1"
for %%i in (!rnd!) do copy "!file[%%i]!" "!Destination!"
)
call :processFolder
cd ..
)
exit /B
Here is anther approach using xcopy /L to walk through all files in the source directory, which does not actually copy anything due to /L but returns paths relative to the source directory. For explanation of the code see all the remarks:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define source and destination directories here:
set "SOURCE=%dp~1"
set "DESTIN=H:\Temp"
rem Change to source directory:
cd /D "%SOURCE%"
rem Reset index number:
set /A "INDEX=0"
rem Walk through output of `xcopy /L`, which returns
rem all files in source directory as relative paths;
rem `find` filters out the summary line; `echo` appends one more line
rem with invalid path, just to process the last item as well:
for /F "delims=" %%F in ('
2^> nul xcopy /L /S /I /Y "." "%TEMP%" ^
^| find ".\" ^
^& echo^(C:\^^^|\^^^|
') do (
rem Store path to parent directory of current item:
set "CURRPATH=%%~dpF"
setlocal EnableDelayedExpansion
if !INDEX! EQU 0 (
rem First item, so build empty directory tree:
xcopy /T /E /Y "." "%DESTIN%"
endlocal
rem Set index and first array element, holding
rem all files present in the current directory:
set /A "INDEX=1"
set "ITEMS_1=%%F"
) else if "!CURRPATH!"=="!PREVPATH!" (
rem Previous parent directory equals current one,
rem so increment index and store current file:
set /A "INDEX+=1"
for %%I in (!INDEX!) do (
endlocal
set /A "INDEX=%%I"
set "ITEMS_%%I=%%F"
)
) else (
rem Current parent directory is not the previous one,
rem so generate random number from 1 to recent index
rem to select a file in the previous parent directory,
rem perform copying task, then reset index and store
rem the parent directory of the current (next) item:
set /A "INDEX=!RANDOM!%%!INDEX!+1"
for %%I in (!INDEX!) do (
xcopy /Y "!ITEMS_%%I!" "%DESTIN%\!ITEMS_%%I!"
endlocal
set /A "INDEX=1"
set "ITEMS_1=%%F"
)
)
rem Store path to parent directory of previous item:
set "PREVPATH=%%~dpF"
)
endlocal
exit /B
For this approach the destination directory can also be located within the source directory tree.
How can I get drive the valid drive letters from A to Z with the "for loop" in windows command line (cmd.exe)?
Example, list all files in a drive root folder, should be something like (conceptual):
for %f in (A..Z) do dir %f:\
or aproximating existing functionality:
for /L in (A, Z, 1) do echo %f:\
Close, but it's more like this.
for %%p in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if not exist %%p:\nul set FREEDRIVELETTER=%%p
EDIT: Here is a powershell way, not sure if off-topic for your needs
Loops the Upper Case Alphabet
65..90 | foreach {[char]$_;Write-Host "Do Something"}
or Lower Case Alphabet
97..122 | foreach {[char]$_;Write-Host "Do Something"}
Maybe this will work from a batch file.
#ECHO OFF
start /b /wait powershell.exe "97..122 | foreach {$a=[char]$_ ;dir $a:\}"
PAUSE
To loop through all drive letters without explicitly stating them you could use forfiles (which is delivered with all Windows versions past Vista, I believe) and its capability to expand hex. codes 0xHH, together with exit to set the exit code and the hidden variable =ExitCode to convert the exit code to a hexadecimal value, like in this example code:
#echo off
for /L %%C in (0x41,1,0x5A) do (
cmd /C exit %%C
for /F %%D in ('
forfiles /P "%~dp0." /M "%~nx0" /C "cmd /C echo 0x%%=ExitCode:~-2%%"
') do echo %%D:\
)
This is quite slow though, because there are several cmd instances opened and closed.
To loop through all available drives, including network drives and also such established by subst, you could use the following code, based on wmic:
for /F "skip=1" %%C in ('wmic LogicalDisk get DeviceID') do for /F %%D in ("%%C") do echo %%D\
To loop through all local drives, you could use the following code, again based on wmic:
for /F "skip=1" %%C in ('wmic Volume where "DriveLetter is not Null" get DriveLetter') do for /F %%D in ("%%C") do echo %%D\
To loop through all local drives, but based on mountvol, you could use the following code instead:
for /F %%C in ('mountvol ^| find ":\"') do echo %%C
Finally, for the sake of completeness, to loop through all drives that have been established by subst, use the this code:
for /F "delims=\" %%C in ('subst') do echo %%C\
The best way I found was using WMI
wmic volume get "caption"
gives just the valid drive letters...
Still searching for a way to do it without external tools/libs/modules (like WMI)
To add onto the answer of aschipfl, here is how you can programatically generate a string variable that contains all the alphabet letters for iterating through, (both upper and lower) though its kinda clunky:
#ECHO OFF
setlocal enabledelayedexpansion
FOR /F "tokens=1,2" %%a IN ('ECHO 65 90 ^& ECHO 97 122') DO (
FOR /L %%i IN (%%a,1,%%b) DO (cmd /c exit %%i & set alpha=!alpha! !=exitcodeAscii!))
echo %alpha%
pause
I was working on doing this to use with findstr, but it will work here as well. If you want to only generate the upper or lower letters I'll leave that exercise to the reader.
After generating the string this way you can use the variable in aschipfl's answer above:
for %%p in (%alpha%) do if not exist %%p:\nul set FREEDRIVELETTER=%%p
Here you go, you can iterate through all drives with a for loop now.
#echo off
setlocal enableDelayedExpansion
cls
REM getting the output from fsutil fsinfo drives and putting it in the ogdrives variable
FOR /F "tokens=* USEBACKQ" %%F IN (`fsutil fsinfo drives`) DO (
SET ogdrives=%%F
)
REM making the drives variable the same as the ogdrives variable so it can be manipulated
set drives=!ogdrives!
REM formating the out so that it looks like 1+1+1+... for every drive that is connected
set drives=!drives:Drives^: =!
set drives=!drives:^:\=1!
set drives=!drives: =+!
REM still formating to find out how many drives there are, this bit gets rid of any letters there are
set charms=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
for /L %%N in (10 1 62) do (
for /F %%C in ("!charms:~%%N,1!") do (
set drives=!drives:%%C=!
)
)
REM last for finding out the number, this removes the last characters since it is a leading + that shouldnt be there
set drives=!drives:~0,-1!
REM num is now the variable that contains the number of drives connected
set /a num=!drives!
REM reseting the drives variable to the original output so it can be manipulated again
set drives=!ogdrives!
REM this time it is being formated to list the drives as a solid string of drive letters like ABCD
set drives=!drives:Drives^: =!
set drives=!drives:^:\=!
set drives=!drives: =!
REM this is to iterate through that string of drive letters to seperate it into multiple single letter variables that are correlated to a number so they can be used later
:loop
REM the iter variable holds how many times this has looped so that when it hits the final drive it can exit
set /a iter=!iter!+1
REM the pos variable is the position in the string of drive letters that needs to be taken out for this iteration
set /a pos=!iter!-1
REM this sets the driveX variable where X is the drives correlated number to the letter of that drive from the long string of drive letters by using the pos variable
set drive!iter!=!drives:~%pos%,1!
REM this is checking to see if all drives have been assigned a number and if it has it will exit the loop
if !iter!==!num! goto oloop
goto loop
:oloop
REM drives are stored in variables %driveX% where X represents the drive number
REM the number of drives are stored in the %num% variable
REM below is an example for iterating through drives
REM this is an example of how to use the information gathered to iterate through the drives
REM we are using a for loop from 1 to the number of drives connected
for /L %%n in (1 1 !num!) do (
REM for every drive that is connected this will be ran
REM %%n contains a number which will increase since its a for loop
REM the drive driveX variable can then be used since drive1=A and drive2=B etc
echo drive %%n is !drive%%n!
REM you can see how i have embedded a variable inside a variable to create an array of sorts.
)
pause
exit
REM the actual variable names are drive1 drive2 drive3 but so that we can iterate through them we can just use a for loop and put the number in the variable
REM one way you can use this is with the where command since it will only search one drive at a time
REM you can do this like this
for /L %%n in (1 1 !num!) do (
where /R !drive%%n!:\ *.txt
)
REM this will return a list of all txt files in the entire system since it searches all drives.