【问题标题】:Getting a free drive letter获得免费驱动器号
【发布时间】:2012-09-19 03:09:01
【问题描述】:

我在this answer 中看到了Get-NextFreeDrive 函数,我想知道是否有更有效的方法来执行此操作。似乎链接答案中的函数会继续遍历所有字母,即使它已经找到了一个空闲的驱动器号。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    在 PowerShell 杂志上,我们举办了一场脑筋急转弯比赛,以找出您问题的最短答案。检查这个:

    http://www.powershellmagazine.com/2012/01/12/find-an-unused-drive-letter/

    有几个答案,但这是我最喜欢的一个:

    ls function:[d-z]: -n | ?{ !(test-path $_) } | random
    

    【讨论】:

    • 这只是获得一个随机可用的驱动器号,而不是第一个可用的驱动器号。
    • @Nick - 可以通过将 random 替换为 select -First 1 来解决此问题
    • 我们只是在那里使用 RegEx。功能:附加从 d 到 z 的字母,然后是 :.
    • @ravikanth 啊,它使用wildcard syntax 搜索名为"function:" 的PS 驱动器。无论路径是否存在,每个可能的驱动器号都有一个函数。棘手!
    • 这个答案具有误导性,它可能会返回没有媒体的现有驱动器(如 cd-rom)。这是一个更好的版本:powershell.com/cs/media/p/202.aspx
    【解决方案2】:

    我的两分钱:

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

    有效[CHAR] 的范围是68..90,添加检查[char]$_[0] -gt 90 是否会避免意外结果。 如果某个单元是映射的网络驱动器,它总是返回主要的连续驱动器,例如:

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

    命令返回 s: 而不是 e: 作为 [string]

    这给出了第一个空闲驱动器号(有点难看..有人可以做得更好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 
    

    【讨论】:

      【解决方案3】:

      我喜欢这种方式,原因如下:

      1. 它不需要 WMI,只需要常规的 powershell cmdlet
      2. 非常清晰易读
      3. 它可以让您轻松排除特定的驱动器号
      4. 它可以让您轻松地以您想要的任何顺序订购驱动器号
      5. 它找到第一个未使用的驱动器并对其进行映射,然后完成。

        $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
            }
        }
        

      【讨论】:

        【解决方案4】:

        这就是我想出的。我需要从 A 到 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
        
        • 这会得到一个字母 A..Z 的数组
        • 然后从 WMI 获取一个已经在使用的字母数组
        • 接下来使用比较运算符 -notcontains 生成一个未使用的字母数组
        • 最后输出一个字母。

        【讨论】:

          【解决方案5】:
          $taken = Get-WmiObject Win32_LogicalDisk | Select -expand DeviceID
          $letter = 65..90 | ForEach-Object{ [char]$_ + ":" }
          (Compare-Object -ReferenceObject $letter -DifferenceObject $taken)[1].InputObject
          

          只是为了好玩,多写一行代码(笑)。如果你想变得笨拙,你可以跳过实例化变量,直接将它们通过管道传递到 -Ref 和 -Diff 中,尽管这样做可能应该受到打击。 :)

          选择 [1] 以避免获得 A: 驱动器,以防万一这可能使事情复杂化。

          【讨论】:

            【解决方案6】:

            我必须编写一个适用于 Powershell V2.0 的函数。 以下函数将返回下一个可用的字母,它也可以获取一个排除字母作为参数:

            Function AvailableDriveLetter ()
            {
            param ([char]$ExcludedLetter)
            $Letter = [int][char]'C'
            $i = @()
            #getting all the used Drive letters reported by the Operating System
            $(Get-PSDrive -PSProvider filesystem) | %{$i += $_.name}
            #Adding the excluded letter
            $i+=$ExcludedLetter
            while($i -contains $([char]$Letter)){$Letter++}
            Return $([char]$Letter)
            }
            

            假设您的操作系统报告驱动器号 C:,E:,F: 和 G: 被使用。

            运行:$First = AvailableDriveLetter,将导致 $First 包含 'D'

            运行:$Sec = AvailableDriveLetter -ExcludedLetter $First,将导致 $Sec 包含 'H'

            【讨论】:

              【解决方案7】:

              另一种方式...

              $DriveList = Get-PSDrive -PSProvider filesystem | foreach({($_.Root).Replace(":\","")})
              $AllDrives = [char[]]([int][char]'E'..[int][char]'Z')
              $NextDriveLetter = ($AllDrives | Where-Object { $DriveList -notcontains $_ } | Select-Object -First 1) + ":"
              

              【讨论】:

                【解决方案8】:

                我自己发现当前接受的答案 (ls function:[d-z]: -n | ?{ !(test-path $_) } | random) 确实可以返回东西像 CD 驱动器。

                我做了这个以从阵列中排除任何本地驱动器:

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

                它将返回第一个可用的字母。如果您更喜欢最后一个可用的字母,只需将 Select-Object -first 1 更改为 Select-Object -last 1

                【讨论】:

                  【解决方案9】:

                  我发现 Test-Path 将我的空 CD-Drive 评估为 False,这是另一种替代方法,它将比较字母表中的每个字母,直到找到文件系统中不存在的一个,然后将该驱动器作为输出返回。

                  $DriveLetter = [int][char]'C'
                  WHILE((Get-PSDrive -PSProvider filesystem).Name -contains [char]$DriveLetter){$DriveLetter++}
                  Write-Host "$([char]$Driveletter):"
                  

                  【讨论】:

                    【解决方案10】:

                    只是要添加一个适用于远程驱动器号的 $computer 将是输入,$driveletter 将包含远程计算机上的下一个可用驱动器

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

                    也许可以缩短它,但在那个长度上,它清楚地看到发生了什么

                    【讨论】:

                      【解决方案11】:

                      这似乎有点像“我也是”的答案,但我注意到所有其他答案都使用-contains-notcontains,我只是不喜欢这些解决方案。所以这可能不是非常有效,但我更喜欢它。这段代码(对我而言)的目的是找到我可以用来创建驱动器映射的第一个驱动器。

                      $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
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2016-11-28
                        • 2012-05-24
                        • 2020-12-15
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多