【发布时间】:2012-09-19 03:09:01
【问题描述】:
我在this answer 中看到了Get-NextFreeDrive 函数,我想知道是否有更有效的方法来执行此操作。似乎链接答案中的函数会继续遍历所有字母,即使它已经找到了一个空闲的驱动器号。
【问题讨论】:
标签: powershell
我在this answer 中看到了Get-NextFreeDrive 函数,我想知道是否有更有效的方法来执行此操作。似乎链接答案中的函数会继续遍历所有字母,即使它已经找到了一个空闲的驱动器号。
【问题讨论】:
标签: powershell
在 PowerShell 杂志上,我们举办了一场脑筋急转弯比赛,以找出您问题的最短答案。检查这个:
http://www.powershellmagazine.com/2012/01/12/find-an-unused-drive-letter/
有几个答案,但这是我最喜欢的一个:
ls function:[d-z]: -n | ?{ !(test-path $_) } | random
【讨论】:
random 替换为 select -First 1 来解决此问题
我的两分钱:
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
【讨论】:
我喜欢这种方式,原因如下:
它找到第一个未使用的驱动器并对其进行映射,然后完成。
$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
}
}
【讨论】:
这就是我想出的。我需要从 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
【讨论】:
$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: 驱动器,以防万一这可能使事情复杂化。
【讨论】:
我必须编写一个适用于 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'
【讨论】:
另一种方式...
$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) + ":"
【讨论】:
我自己发现当前接受的答案 (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
【讨论】:
我发现 Test-Path 将我的空 CD-Drive 评估为 False,这是另一种替代方法,它将比较字母表中的每个字母,直到找到文件系统中不存在的一个,然后将该驱动器作为输出返回。
$DriveLetter = [int][char]'C'
WHILE((Get-PSDrive -PSProvider filesystem).Name -contains [char]$DriveLetter){$DriveLetter++}
Write-Host "$([char]$Driveletter):"
【讨论】:
只是要添加一个适用于远程驱动器号的 $computer 将是输入,$driveletter 将包含远程计算机上的下一个可用驱动器
67..90 | foreach {if(((GWmi win32_logicaldisk -computer $computer -Property DeviceID).deviceID).Substring(0,1) -notcontains [char]$_){$driveLetter = [char]$_; break}}
也许可以缩短它,但在那个长度上,它清楚地看到发生了什么
【讨论】:
这似乎有点像“我也是”的答案,但我注意到所有其他答案都使用-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
【讨论】: