Author Posts

August 27, 2015 at 10:34 am

Hi again,

I'm trying to create a code that shows me what IPs are available in a range:

Let's suppose this string variable content:

192.168.47.1
192.168.47.2
192.168.47.3
192.168.47.4
192.168.47.6
192.168.47.7
192.168.47.8
192.168.47.9
192.168.47.14
192.168.47.47
192.168.47.244

Is there an easy way to know the first IP address available?

August 27, 2015 at 10:44 am

Is the input list available addresses or used addresses?

August 27, 2015 at 10:45 am

If it's being fed into your script as an array, you can always pipe it to Select-Object -First 1 and it'll give you the first object in your array. If it's a continuous string, you'll have to get more creative. For Example:

[string]$IPAddress = Get-Content C:\scripts\ipaddress.txt

$IPAddress.Split(' ') | Select-Object -First 1

Will change your output from this:

PS C:\WINDOWS\system32> $IPAddress
192.168.47.1 192.168.47.2 192.168.47.3 192.168.47.4 192.168.47.6 192.168.47.7 192.168.47.8 192.168.47.9 192.168.47.14 192.168.47.47 1
92.168.47.244

To this:

PS C:\WINDOWS\system32> $IPAddress.Split(' ')
192.168.47.1
192.168.47.2
192.168.47.3
192.168.47.4
192.168.47.6
192.168.47.7
192.168.47.8
192.168.47.9
192.168.47.14
192.168.47.47
192.168.47.244

PS C:\WINDOWS\system32> $IPAddress.Split(' ') | Select-Object -First 1
192.168.47.1

August 27, 2015 at 11:02 am

Tim Curwick,

Used addresses.

Will Anderson,

It's an array, but I need the first one available.
In my example it should be IP address: 192.168.47.5

August 27, 2015 at 11:14 am

This would compare the entire range against what is used and provide the first IP. The only thing that gets a bit more sticky is if you need to sort because you would have to pad each subnet with zero, but this is the general code you'll need:

#Get used IP's from a file
$ipFile = Get-Content C:\Temp\test.txt

#Convert it to a PSObject 
$usedIPs = $ipFile | foreach{
    New-Object -TypeName PSObject -Property @{IP=$_}
}

#Create a PSObject with all possible IPs in the range
$allIPs = for ($i=1;$i -le 255;$i++){
    New-Object -TypeName PSObject -Property @{IP=("192.168.47.{0}" -f $i)}
}

#Compare the objects and that are in the all IP's and not in the used and select the first one
Compare-Object -ReferenceObject $allIPs -DifferenceObject $usedIPs -Property IP -PassThru | 
Where {$_.SideIndicator -eq "< ="} |
Select -ExpandProperty IP -First 1

August 27, 2015 at 11:26 am

$UsedIPs = @'
192.168.47.1
192.168.47.2
192.168.47.3
192.168.47.4
192.168.47.6
192.168.47.7
192.168.47.8
192.168.47.9
192.168.47.14
192.168.47.47
192.168.47.244
'@

$UsedOctets = $UsedIPs.Split( "`n" ) | ForEach { [int]$_.Split( '.' )[-1] }

$FirstAvailableOctet = 1..255 | Where { $UsedOctets -notcontains $_ } | Select -First 1

"192.168.47.$FirstAvailableOctet"

August 28, 2015 at 7:57 am

Slightly different approach using the "[version] magic" to split out the octets.

$usedIps = @'
192.168.47.1
192.168.47.2
192.168.47.3
192.168.47.4
192.168.47.6
192.168.47.7
192.168.47.8
192.168.47.9
192.168.47.14
192.168.47.47
192.168.47.244
'@ -split "`r`n"
$pattern = [regex]"((\d{1,3}\.){3})"
$ptr = 0
$usedIps[0] -match $pattern | Out-Null
$net = $Matches[1]
$usedIps | foreach {
    if (([version]$_).Revision -eq ($ptr + 1))
    {
        Write-Verbose "Saw $_"
        $ptr++
    }
    else
    {
        "Next IP is $net$($ptr + 1)"
        break
    }
}

August 31, 2015 at 3:12 am

Will Anderson, Tim Curwick, Rob Simmers and Bob McCoy,

Thank you all for the help.
I'm having some personal problems at the moment and that's why I took so long to answer.

Thank you once again!