私はこの回答Get-NextFreeDrive
の関数を見て、これを行うためのより効率的な方法があるかどうか疑問に思いました。リンクされた回答の関数は、すでに空きドライブ文字を見つけた場合でも、すべての文字を処理し続けるようです。
11 に答える
PowerShell Magazineでは、頭の体操コンテストを実施して、質問に対する最短の回答を見つけました。これをチェックして:
http://www.powershellmagazine.com/2012/01/12/find-an-unused-drive-letter/
いくつかの答えがありますが、ここに私のお気に入りがあります:
ls function:[d-z]: -n | ?{ !(test-path $_) } | random
私の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:
これにより、最初の無料のドライブ文字が表示されます(少し醜い..誰かがより良い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
次の理由で、私はこの方法が好きです。
- WMIは必要ありません。通常のPowerShellコマンドレットだけです。
- 非常に明確で読みやすいです
- 特定のドライブレターを簡単に除外できます
- ドライブレターを好きな順序で簡単に注文できます
最初の未使用のドライブレターを見つけてマップし、それで終了します。
$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
- これは文字の配列A..Zを取得します
- 次に、WMIからすでに使用されている文字の配列を取得します
- 次に、比較演算子-notcontainsを使用して、使用されていない文字の配列を生成します。
- 最後に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に直接パイプするだけで、まとまりのないものになりたい場合は、おそらくそれを行うために平手打ちする必要があります。:)
問題が複雑になる可能性がある場合に備えて、A:ドライブを取得しないように[1]を選択します。
PowershellV2.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)
}
OSがドライブ文字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:[dz]:-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ドライブを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