#1 26 Jun 2008 22:09

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

find free drive letter for temp drive mappings but skip cdrom

I did this:

setlocal enabledelayedexpansion
for %%a in (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 %%a:\ (
      if 1!tmpsource!==1 (
         set tmpsource=%%a:
         ) else (
            if 1!tmpdest!==1 set tmpdest=%%a:
      )
   )
)

so I could set a couple of temporary drive mappings for a script.  Anyway--my cdrom drive is set to l: and this code will set l: as an available drive letter -- which it isn't.  The "if not exist %%a:\" portion is true for the cdrom drive (if there isn't a cd in the drive).

Now obviously I can get rid of the "l" in the for list but I'm trying for something that can be run on different machines where I don't know the drive letters . . .

Offline

#2 27 Jun 2008 11:18

Simon Sheppard
Super Administrator
Registered: 27 Aug 2005
Posts: 1,018
Website

Re: find free drive letter for temp drive mappings but skip cdrom

If you do
NET USE * \\server\your_share
That will assign the next available drive letter, but still leaves the problem that you may need to know *which* letter it picked

A better option is

Pushd \\server\your_share

That will assign a temporary drive map, starting at the last available letter, it will then CD to the mapped drive/folder.
When you are finished with it, a simple POPD will remove the temporary map and put your current directory back where it started.

Offline

#3 01 Jul 2008 17:52

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

Re: find free drive letter for temp drive mappings but skip cdrom

Well, nice idea--but I'm not using net use.

First I'm using vmware server and mounting a virtual disk.  Then I'm using the subst command for the 2nd option.  I have other scripts that would use it for netware drive mapping.

I suppose I could use a net use * command and figure out what drive it uses, then delete the mapping and use the drive.  Seems a bit excessive, though.  There should be some way to list local drives . . .

Ted

Offline

#4 03 Jul 2008 12:13

bluesxman
Member
From: UK
Registered: 29 Dec 2006
Posts: 1,083

Re: find free drive letter for temp drive mappings but skip cdrom

Oh but there is a way!

FSUTIL FSINFO DRIVES

The output produced by the above is a little "funny", see also this post for a method to manipulate it into a usable form: http://www.ss64.org/viewtopic.php?id=327

:EDIT:
Alternatively, you could probably try accessing each drive letter in turn, looking for the error "The system cannot find the drive specified." as that should indicate an available drive letter.  An empty CD/DVD drive should give "The device is not ready."; any other in-use letter should return no error at all.

Last edited by bluesxman (03 Jul 2008 12:23)


cmd | *sh | Ruby | Chef

Offline

#5 03 Jul 2008 21:12

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

Re: find free drive letter for temp drive mappings but skip cdrom

Nice.  So it could look like this:

setlocal enabledelayedexpansion
FSUTIL FSINFO DRIVES > }{.tmp
for %%a in (f g h i j k l m n o p q r s t u v w x y z) do (
   find /i "%%a:\" }{.tmp
   if errorlevel 1 (
      if 1!tmpsource!==1 (
         set tmpsource=%%a
         ) else (
            if 1!tmpdest!==1 set tmpdest=%%a
      )
   )
)

I could manipulate it further to exit the for loop when 2 drives have been found.

Thanks!

Last edited by avery_larry (21 Jul 2008 19:14)

Offline

#6 24 Jul 2008 21:38

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

Re: find free drive letter for temp drive mappings but skip cdrom

I've come up with this:

@setlocal enabledelayedexpansion
@echo off


::This file will echo a free drive letter.  It will also set a variable
::to that drive letter if it is passed the variable name like this:
::freedrv variablename


for /f "tokens=*" %%a in ('FSUTIL FSINFO DRIVES') do set freedrv_drives=%%a
for %%a in (z y x w v u t s r q p o n m l k j i h g f) do (
   echo %freedrv_drives%|find /i "%%a:\" >nul 2>nul
   if errorlevel 1 set freedrv_drive=%%a
)
:end
endlocal && echo %freedrv_drive%&&if not 1%1==1 set %1=%freedrv_drive%
:eof

I was wondering if there's a nice way to exit the for loop instead of looping through z ... f.  I've accomplished this in the past using the following (abbreviated code):

if not 1%1==1 (
   echo %freedrv_drives%|find /i "%1:\" >nul 2>nul
   if errorlevel 1 exit&&set freedrv_drive=%1
   goto eof
)
cmd /q /d /c "for %%a in (1 2 3) do call %0 %%a"
:eof

I can't figure out how to pass the variable out of the for loop that's run in a separate CMD shell.  The line "exit&&set . . ." doesn't work.

Offline

#7 24 Jul 2008 22:02

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

Re: find free drive letter for temp drive mappings but skip cdrom

Actually, this doesn't work:

for /f "tokens=*" %%a in ('FSUTIL FSINFO DRIVES') do set freedrv_drives=%%a

The variable is set to C:\

Any idea why?  Seems like the output maybe uses LF?

Offline

#8 25 Jul 2008 09:28

bluesxman
Member
From: UK
Registered: 29 Dec 2006
Posts: 1,083

Re: find free drive letter for temp drive mappings but skip cdrom

I refer you back to the post I referred you to in my original post (does that make sense?) ... Look here.


cmd | *sh | Ruby | Chef

Offline

#9 25 Jul 2008 18:38

Simon Sheppard
Super Administrator
Registered: 27 Aug 2005
Posts: 1,018
Website

Re: find free drive letter for temp drive mappings but skip cdrom

On the FSUTIL page I've now added a simplified version of bluesxmans script - http://ss64.com/nt/fsutil.html

To keep the example as simple and generic as possible it just lists the drives and doesn't set any variable.

An alternative method to get drive information is PSINFO -d but that is noticeably slower than FSUTIL

Offline

#10 29 Jul 2008 17:18

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

Re: find free drive letter for temp drive mappings but skip cdrom

bluesxman wrote:

I refer you back to the post I referred you to in my original post (does that make sense?) ... Look here.

Sorry -- didn't read very well.  Thank you all very much.

Offline

#11 29 Jul 2008 17:33

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

Re: find free drive letter for temp drive mappings but skip cdrom

In the code from the other thread:

@echo off
setlocal enabledelayedexpansion
set drives=
for /f "usebackq tokens=1*" %%a in (`FSUTIL FSINFO DRIVES ^| find ":"`) do (
    if /i "%%a" NEQ "Drives:" (
        set "drives=!drives! %%a"
        echo:%%a
    ) ELSE (
        set "drives=!drives! %%b"
        echo:%%b
    )
)

set drives=%drives:~1%
echo:"%drives%"

I don't see the else statement ever running:

    ) ELSE (
        set "drives=!drives! %%b"
        echo:%%b

Did I miss something or is it just extra code?   wink

Offline

#12 29 Jul 2008 18:25

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

Re: find free drive letter for temp drive mappings but skip cdrom

After much testing, I've come up with the following:

@setlocal enabledelayedexpansion
@echo off


::This file will echo a free drive letter.  It will also set a variable
::to that drive letter if it is passed the variable name like this:
::freedrv variablename

set freedrv_drives=
for /f "usebackq tokens=1*" %%a in (`FSUTIL FSINFO DRIVES ^| find ":"`) do (
   if /i "%%a" NEQ "Drives:" set freedrv_drives=!freedrv_drives! %%a
)
call :process
goto end

:process
for %%a in (z y x w v u t s r q p o n m l k j i h g f) do (
   echo %freedrv_drives% | find /i "%%a:\" >nul 2>nul
   if errorlevel 1 (
      set freedrv_drive=%%a
      exit /b
   )
)
goto eof

:end
endlocal && echo %freedrv_drive%&&if not 1%1==1 set %1=%freedrv_drive%
:eof

The call :label portion allows you to use an exit /b command to effectively abort a for loop.  I swear I've tried that before but I just have had something wrong.

Offline

#13 30 Jul 2008 10:14

bluesxman
Member
From: UK
Registered: 29 Dec 2006
Posts: 1,083

Re: find free drive letter for temp drive mappings but skip cdrom

avery_larry wrote:

I don't see the else statement ever running:

Au contraire, the "ELSE" command will execute for the very first drive in the list.  Trust me, I'm a professional.

OK I'll explain.

If you run the fsutil fsinfo drives | find ":" command at the CMD prompt you'll get a response in this format:

Drives: C:\
D:\
E:\
F:\
G:\
H:\
I:\
K:\
X:\
Y:\

So when slicing up the output, we want "%%a" as this represents the drive letter; except in the first line of output, where "%%a" = "Drives:", in which case we want "%%b".

It's not going to cause a big problem with your code, because the first in-use letter is very likely to be "A" or "C", and you aren't entertaining the possibility of a free letter below "F".


cmd | *sh | Ruby | Chef

Offline

#14 30 Jul 2008 22:54

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

Re: find free drive letter for temp drive mappings but skip cdrom

bluesxman wrote:

If you run the fsutil fsinfo drives | find ":" command at the CMD prompt you'll get a response in this format:

Drives: C:\
D:\
E:\
F:\
G:\
H:\
I:\
K:\
X:\
Y:\

On the computer I was using (Win 2003 server), the output is as follows:

Drives:
C:\
D:\
E:\
F:\
G:\
H:\
I:\
K:\
X:\
Y:\

On WinXP it is as you stated.  I'll add it back in since it doesn't hurt anything on Win 2003 server.

Offline

#15 31 Jul 2008 10:00

bluesxman
Member
From: UK
Registered: 29 Dec 2006
Posts: 1,083

Re: find free drive letter for temp drive mappings but skip cdrom

I really should check on different Windows versions before getting on my high horse smile


cmd | *sh | Ruby | Chef

Offline

#16 05 Sep 2008 20:11

avery_larry
Member
Registered: 11 Jul 2007
Posts: 266

Re: find free drive letter for temp drive mappings but skip cdrom

This may be a bit more elegant: (tested only on WinXP)

@setlocal enabledelayedexpansion
@echo off

::This file will echo a free drive letter.  It will also set a variable
::to that drive letter if it is passed the variable name like this:
::freedrv variablename

for /f "usebackq tokens=1*" %%a in (`FSUTIL FSINFO DRIVES ^| find ":"`) do (
   if /i "%%a" NEQ "Drives:" (
      set freedrv_drives=!freedrv_drives! %%a
      ) else (
         set freedrv_drives=%%b
   )
)

for %%a in (z y x w v u t s r q p o n m l k j i h g f e d c b a) do (
   echo %freedrv_drives% | find /i "%%a:\" >nul 2>nul
   if errorlevel 1 (
      endlocal
      echo %%a
      if not 1%1==1 set %1=%%a
      exit /b
   )
)

Last edited by avery_larry (05 Sep 2008 20:14)

Offline

#17 19 Oct 2012 22:27

QuickLearnin00b
Member
Registered: 19 Oct 2012
Posts: 1

Re: find free drive letter for temp drive mappings but skip cdrom

How about just:

for %%a in (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 EXIST %%a:\ (echo %%a drive exists) ELSE (set MountedDriveLetter=%%a && GOTO break)
)
:break

Offline

#18 22 Oct 2012 14:43

bluesxman
Member
From: UK
Registered: 29 Dec 2006
Posts: 1,083

Re: find free drive letter for temp drive mappings but skip cdrom

Because that will erroneously report a CD-ROM without a CD loaded as being available.


cmd | *sh | Ruby | Chef

Offline

#19 22 Oct 2012 18:49

dbenham
Member
From: U.S. east coast
Registered: 15 Apr 2012
Posts: 111

Re: find free drive letter for temp drive mappings but skip cdrom

I believe WMIC is faster, and it does not require admin privs.

@echo off
setlocal enableDelayedExpansion
set "drives=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for /f "delims=:" %%A in ('wmic logicaldisk get caption') do set "drives=!drives:%%A=!"

echo all unused letters = %drives%
echo next unused letter = %drives:~0,1%
echo last unused letter = %drives:~-1%

Dave Benham

Offline

#20 05 Sep 2013 20:06

npocmaka
Member
From: Bulgaria
Registered: 03 Dec 2009
Posts: 430

Re: find free drive letter for temp drive mappings but skip cdrom

one more way (requires admin privileges ):

fltMc volumes

edit:
shows only virtual cdroms. So cannot be used to find free letter.

Last edited by npocmaka (05 Sep 2013 21:14)

Offline

#21 06 Sep 2013 06:23

carlos
Member
From: Chile
Registered: 04 Nov 2008
Posts: 246
Website

Re: find free drive letter for temp drive mappings but skip cdrom

Hello. I remember write that function:

:volume
For %%# in (B Z Y X W V U T S R Q
P O N M L K J I H G F E D C A
) Do (Vol %%#: || Net Use %%#:) >Nul 2>&1 || (
Set "volume=%%#:" &Goto :Eof)
Echo Error. None volume available.

But is more fast use a non letter volume directly, because is most probably that it letter is never used.

Offline

#22 21 May 2017 12:00

Andrew.au
Member
Registered: 21 May 2017
Posts: 5

Re: find free drive letter for temp drive mappings but skip cdrom

Using internal commands only, get the next available drive, skipping optical drives:

vol Z: Y: X: W: V: U: T: S: R: Q: P: O: N: M: L: K: J: I: H: G: F: E: D: C: 1>nul 2>%temp%\volErr.txt
for /F "tokens=5 delims=. " %%A in (%temp%\volErr.txt) do @set NAD=%%A
@echo.
@echo Next available drive is; %NAD%

Offline

Board footer

Powered by FluxBB