Getting a free drive letter

后端 未结 11 451
青春惊慌失措
青春惊慌失措 2020-12-10 13:40

I saw the Get-NextFreeDrive function in this answer and I wondered if there was a more efficient way to do this. It appears that the function in the linked answ

相关标签:
11条回答
  • 2020-12-10 13:57

    I found to my own cost that the currently accepted answer (ls function:[d-z]: -n | ?{ !(test-path $_) } | random) can indeed return things like CD drives.

    I've made this one to exclude any local drives from the array:

    "$([char[]]([char]'D'..[char]'Z')|Where-Object {((Get-WmiObject -Class Win32_LogicalDisk).DeviceID).replace(':','') -notcontains $_ }|Select-Object -first 1):"
    

    It will return the first available letter. If you'd prefer the last available letter just change Select-Object -first 1 to Select-Object -last 1

    0 讨论(0)
  • 2020-12-10 13:59

    This seems a bit like a "me too" answer, but I noticed that all the other answers use -contains or -notcontains and I just didn't like those solutions. So this may not be terribly efficient, but I like it better. The purpose of this code (for me) was to find the first drive that I can use to create a drive mapping.

    $FreeDrive=Get-PSDrive -PSProvider FileSystem | Select-Object -ExpandProperty Name | Where-Object { ($_ -ne "A") -and ($_ -ne "B") -and ($_ -ne "C") } | ForEach-Object { [System.Convert]::ToByte([System.Convert]::ToChar($_)) }
    $FreeDrive=@($FreeDrive)
    if (($FreeDrive.Count -eq 1) -and ($FreeDrive[0] -ne "Z")) { $FreeDrive=[System.Convert]::ToChar($FreeDrive[0]+1) }
    $j=0
    while ((($FreeDrive[$j]+1) -eq $FreeDrive[$j+1]) -and ($j -lt ($FreeDrive.Count-1))) { $j++ }
    $FreeDrive=[System.Convert]::ToChar($FreeDrive[$j]+1)
    $FreeDrive
    
    0 讨论(0)
  • 2020-12-10 14:00

    just going to add one that works for remote drive letters $computer will be the input and $driveletter would contain the next available drive on the remote computer

    67..90 | foreach {if(((GWmi win32_logicaldisk -computer $computer -Property DeviceID).deviceID).Substring(0,1) -notcontains [char]$_){$driveLetter = [char]$_; break}}
    

    might be able to shorten that but at that length its clear to see whats going on

    0 讨论(0)
  • 2020-12-10 14:07

    Here's what I came up with. I need the last available drive letter from A to Z.

    $AllLetters = 65..90 | ForEach-Object {[char]$_ + ":"}
    $UsedLetters = get-wmiobject win32_logicaldisk | select -expand deviceid
    $FreeLetters = $AllLetters | Where-Object {$UsedLetters -notcontains $_}
    $FreeLetters | select-object -last 1
    
    • This gets an array of letters A..Z
    • Then gets an array of the letters already in use from WMI
    • Next produces an array of letters not in use using the comparison operator -notcontains
    • Finally outputs a single letter.
    0 讨论(0)
  • 2020-12-10 14:09

    My two cents:

    get-wmiobject win32_logicaldisk | select -expand DeviceID -Last 1 | 
    % { [char]([int][char]$_[0]  + 1) + $_[1] }
    

    Range of valid [CHAR] is 68..90, adding a check if [char]$_[0] -gt 90 avoid unexpected results. In case some unit is a mapped network drive it return always the major successive, ex.:

    c: system drive
    d: cd/dvd
    r: network mapped drive
    

    the command return s: and not e: as [string]

    This give the first free drive letter ( a little ugly.. someone can do it better IMO):

    $l = get-wmiobject win32_logicaldisk | select -expand DeviceID  | % { $_[0] }
    $s = [int][char]$l[0]
    foreach ( $let in $l )
    {
        if ([int][char]$let -ne $s)
        {
            $ret = [char]$s +":"
            break
        }
    
        $s+=1    
    }
    $ret 
    
    0 讨论(0)
  • 2020-12-10 14:09

    I like this way, for the following reasons:

    1. It doesn't require WMI, just regular powershell cmdlets
    2. It is very clear and easy to read
    3. It easily allows you to exclude specific driveletters
    4. It easily allows you to order the driveletters in any order you would like
    5. It finds the first non used driveletter and maps it, and then it is finished.

      $share="\\Server\Share"
      $drvlist=(Get-PSDrive -PSProvider filesystem).Name
      Foreach ($drvletter in "DEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()) {
          If ($drvlist -notcontains $drvletter) {
              $drv=New-PSDrive -PSProvider filesystem -Name $drvletter -Root $share
              break
          }
      }
      
    0 讨论(0)
提交回复
热议问题