1
param($addr)
$file = get-content $addr

if($addr -eq $null){
        "Please use a valid parameter"
}
else{
        if ($addr -ne './*'){
                write-host $addr
        }
        else{
                write-host $file
        }

}

OUPUT:

./ipAddress.txt

CONTENT:

8.8.8.8
127.0.0.1
208.67.222.222

If I put $file out of the if statement then it works. However, I want to be able to say if the user inputs either a file or an ip address then do this...

4
  • 1
    What's the failure when you leave $file in? Commented Apr 19, 2017 at 17:48
  • It simply outputs the file name, i need the contents of the file. Sorry if that wasn't clear Commented Apr 19, 2017 at 17:50
  • So, assuming you're calling this script Get-Stuff.ps1, you're calling it as .\Get-Stuff.ps1 .\ipAddress.txt and instead of pulling the content of the file, it's just printing the file name? Commented Apr 19, 2017 at 17:56
  • the format would be ./get-Ping.ps1 ./ipAddress.txt Commented Apr 19, 2017 at 17:58

2 Answers 2

4

Stop relying on positional parameters. Use named parameters with parameter sets, and remove the ambiguity:

[CmdletBinding(DefaultParameterSetName='ByFile')]
param(
    [Parameter(
        Mandatory=$true,
        ParameterSetName='ByFile'
    )]
    [ValidateScript( { $_ | Test-File } )]
    [String]
    $Path ,

    [Parameter(
        Mandatory=$true,
        ParameterSetName='ByIP'
    )]
    [System.Net.IPAddress[]]
    $IPAddress
)

$ipAddresses = if ($PSCmdlet.ParameterSetName -eq 'ByFile') {
    $Path | Get-Content
} else {
    $IPAddress
}

foreach ($ip in $ipAddresses) {
    # do something with the IP
}

Invoke it like this:

./get-Ping.ps1 -File ./fileOfIPs.txt

or

./get-Ping.ps1 -IPAddress 10.1.2.3
./get-Ping.ps1 -IPAddress 10.0.0.10,10.0.0.20,8.8.8.8

It even supports multiple IPs given directly.

Alternative

If you must support a positional parameter that can be either, then I suggest testing the IP first:

param($addr)

$ips = if ($addr -as [System.Net.IPAddress]) { # it can be interpreted as an IP
    $addr
} else {
    $addr | Get-Content
}

foreach ($ip in $ips) {
    #do something
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is a good (dare I say 'best'?) practice, and one that I would recommend on general principles, but it's also an advanced technique which I suspect the querent wasn't quite up to.
3

The problem is your comparison in the else clause. -ne only matches - or rather, not-matches - an exact string, without honoring wildcards. Instead, you should use -notlike: if ($addr -notlike "./*") {...}. Note that you'll still have problems if you supply a full path to a file (e.g., D:\Foo\IPs.txt), but the comparison here is your specific problem given the input for your example.

Take a look at Get-Help about_Comparison_Operators

2 Comments

If there was a way give someone a hug over a computer, you sir deserve one. Thank you for your contribution :)
If it worked for you, click on the checkmark below the vote for the answer. It marks the question as solved (and gives me a few points of reputation).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.