Powershell Script to turn CSV with IP Addresses into \\UNCPATH\

Thanks for the help to those who commented! Got this script working like a charm now. Looks like I was breaking the CSV import by deleting headers, and my output needed a variable! Look forward to interacting with the community again in the future.

Now if I import a correctly formatted CSV I get the expected output. Thanks again!

# Powershell script to take a .csv file containing a list of IP addresses 
# and append \\(IPHERE)\C$; for use with a tool that will scan directories on the network

# Built by Justin Sherley with the assistance of Powershell.org members for use in RS&I, Inc
# https://powershell.org/forums/topic/powershell-script-to-append-to-a-csv-with-ip-addresses
# 5/9/2019 | omegatechnologyservices@protonmail.com

# How-to guide found here:

# Read from user to get target directory
$directory = Read-Host -Prompt "Input target directory where files will be stored and written. Example: c:\users\USERNAME\desktop."

# Read from user name of imported file
$importfile = Read-Host -Prompt "Enter the name of the file you are importing. Do not include .csv"

# Read from user desired output file name
$exportfile = Read-Host -Prompt "Enter the name for exported file. Do not include extension"

# Append subdirectories to UNC path for scanning
$subdirectories = Read-Host -Prompt "Enter sub directory for scan. By default the output will be \\XXX.XXX.XXX.XXX\ and scan the entire machine. 
Keep in mind that drive access is hidden over network shares. Include $ in any drives. Input example: C$\users. If scanning entire machine leave blank and hit Enter."

# Combine directory and file name for import

$importfilename = $directory + '\' + $importfile + '.csv'

# Combine directory and file names to complete file path for export

$searchdirectories = $directory + '\' + $exportfile + '.txt'

# Perform append and output files for search list

$outputsearch = Get-Content -path $importfilename | ForEach-Object{'\\' + $_ + '\' + $subdirectories + '; '}
$outputsearch | Out-File -NoNewline $searchdirectories

# Confirmation!

Write-host 'Conversion is complete! Press any key to continue...'
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Original post
Hello! Bare with me as I've only been using PowerShell for 2 days and I've only been scripting for like 90 days (I know some basic C/C++)
I'm using a tool that can scan our network computers for different file types, and it supports separation by "; " (not sure without the space.. it's running right now. But I'll try it afterwards). Instead of manually changing a few hundred IP addresses from
10.0.2.1,
10.0.2.2,
10.0.2.3,
10.0.2.4,
etc
I'd like to output it as
\\10.0.2.1\c$;\\10.0.2.2\c$;\\10.0.2.3\c$;\\10.0.2.4\c$;etc
So that I can easily copy and paste this into the program I'm using. We're talking a couple of hundred IP addresses, and I don't want to type them out by hand haha.
I've written a script that I believe is working halfway, but I get nothing in my output file.
# Powershell script to take a .csv file containing a list of IP addresses # and append \\(IPHERE)\C$; for use with a tool that will scan directories on the network $directory = Read-Host -Prompt "Input target directory." $file = Read-Host -Prompt "Name of CSV file?" $exportfile = Read-Host -Prompt "Name of exported file" $exportfilename = $directory + '\' + $exportfile + '.csv' $importfilename = $directory + '\' + $file + '.csv' Import-Csv -path $importfilename -Delimiter ';' | ForEach-Object{'\\' + $_ + '\C$'} Export-Csv -path $exportfilename -Delimiter ';'
The output I get when I run this command looks like this
Input target directory.: c:\users\mastodon\desktop Name of CSV file?: IPaddress Name of exported file: testing5 \\@{10.0.3.4=10.0.3.10}\C$ \\@{10.0.3.4=10.0.3.15}\C$ \\@{10.0.3.4=10.0.3.101}\C$ \\@{10.0.3.4=10.0.3.102}\C$ \\@{10.0.3.4=10.0.3.5}\C$ \\@{10.0.3.4=10.0.3.115}\C$ cmdlet Export-Csv at command pipeline position 1 Supply values for the following parameters: InputObject:
There's three things i cannot figure out as of right now
  1. Why is it asking me for an InputObject, when my code doesn't use Input-Object? My guess is this has something to do with my ForEach-Object append?
  2. Why are they displaying as "\\@{10.0.3.4=10.0.3.115}\C$" rather than "\\@{10.0.3.115\c$;" (IIRC the @{ } is just placeholders.. but I may be wrong?)
  3. What do I need to supply for syntax for my Export-Csv? Currently, it exports a file with the proper file name and a .csv extension but it contains
    <colgroup><col style="width: 48pt;" width="64" /> </colgroup>
    #TYPE System.String
    Length
    1
    Thanks in advance!

Your Export-Csv cmdlet is expecting something preceding it in it’s pipeline to then export to csv, i.e. it’s InputObject. (“What do you want me to export?”)

I rewrote your example to illustrate:

[pre]
$IPArray = @(‘10.0.0.1’,‘10.0.0.2’,‘10.0.0.3’)

$InputObject = Foreach ($obj in $IPArray) {
[PSCustomObject]@{
‘UNCShare’=“{0}$obj{1}” -f “\”,“\c$”
}
}

$InputObject | Export-Csv -NoTypeInformation -Path C:\test.csv
[/pre]

This would produce a csv with one header - UNCShare. It would look like this:
[pre]
“UNCShare”
“\10.0.0.1\c$”
“\10.0.0.2\c$”
“\10.0.0.3\c$”
[/pre]

Why are they displaying as "\\@{10.0.3.4=10.0.3.115}\C$" rather than "\\@{10.0.3.115\c$;" (IIRC the @{ } is just placeholders.. but I may be wrong?

The @{} are not placeholders, this is called a hashtable in PS. You are returning a hash-literal object. Unless you know you need it, the rule of thumb is to append -NoTypeInformation to Export-Csv. This behavior is now default in PSCore (v6+), and it will default to NoTypeInformation.

What do I need to supply for syntax for my Export-Csv? Currently, it exports a file with the proper file name and a .csv extension but it contains

Export-Csv expects headers in the form of properties. This must be present in the pipeline or -InputObject you are exporting. In my example, you see the header is inherited from the NoteProperty “UncShare” i declared in my PSCustomObject.

Well there’s lots here to comment on but understandable since you’ve said you’re quite new to this. Seems like you’ve dived straight into solving an issue without covering a lot of the basics so if this is something you’re going to pursue I definitely recommend looking into courses from Pluralsight and Microsoft (I believe Microsoft Vitual Academy has been replaced with something else now? Not sure…)

To answer your questions first:

  1. You seem to have placed Export-Csv on a new line, but seemingly your intention was to pass the data from the line before to Export-Csv. Because it's on its own line and no pipeline characters at the end of the line before, PS interprets this command on its own. It's asking for a value for -InputObject as this is a required parameter in the default parameter set for Export-Csv. To correct this you should simply place a pipeline character at the end of the line before Export-Csv.
  2. This is a bit long-winded to explain... Firstly, you're using Import-Csv to read in your data, but from your example it seems the data is simply a list of IP addresses, one per line, with no header. Import-Csv expects a properly formatted, delimited file, including headers (by default). It reads in the data and creates objects with properties and values. In this case it sees the first IP in the list as the header and makes that a property name on the output object. What you've done after using Import-Csv is to create a string value using concatenation: ForEach-Object{'\\' + $_ + '\C$'}. $_ represents the current object in the pipeline, which will be the objects output from Import-Csv. In this instance you're converting the object to a string essentially through your use of concatenation with the + operator. In PS typically when you convert an object into a string the output is displayed as a representation of a property, value pair, eg @{property=value}. Therefore you end up with a string that is '\\', concatenated with the string representation of the object ($_ represents @{property=value}, concatenated with '\C$'.
  3. Export-Csv would not have done anything without having entered a value for -InputObject as it's asked for (see my response to 1), and you've not said what you've entered in the console when prompted, so, based on the output file I can only assume you simply typed something into the console when prompted (just text input), and because Export-Csv expects an object, the info being output is the properties of a string object, as would be from you entering simple text at the prompt.
To get what you want is fairly simple. If you have file.txt (a list of IP addresses, one per line) and your goal is to simply modify that text into a format you require:

[pre]

$Output = Get-Content C:\file.txt | ForEach-Object {“\$_\C$”}

$Output -join “;” | Out-File C:\Output.txt

[/pre]

Get-Content over Import-Csv since you seem to have a simple list of values rather than a properly formatted CSV file. Pipe to ForEach-Object to create the string output you require with each item from your input list. That is all assigned to a variable called $Output, then the next line uses the -join operator to join each item with a semicolon, then pipe to Out-File to generate your desired output file.

Hope this helps.

[quote quote=155948]Your Export-Csv cmdlet is expecting something preceding it in it’s pipeline to then export to csv, i.e. it’s InputObject. (“What do you want me to export?”)

I rewrote your example to illustrate:

PowerShell
10 lines
<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59781px; left: 51px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
2
3
4
5
6
7
8
9
10
$IPArray = @('10.0.0.1','10.0.0.2','10.0.0.3')
$InputObject = Foreach ($obj in $IPArray) {
[PSCustomObject]@{
'UNCShare'="{0}$obj{1}" -f "\\","\c$"
}
}
$InputObject | Export-Csv -NoTypeInformation -Path C:\test.csv
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This would produce a csv with one header – UNCShare. It would look like this:
PowerShell
5 lines
<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59781px; left: 44px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
2
3
4
5
"UNCShare"
"\\10.0.0.1\c$"
"\\10.0.0.2\c$"
"\\10.0.0.3\c$"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Why are they displaying as "\\@{10.0.3.4=10.0.3.115}\C$" rather than "\\@{10.0.3.115\c$;" (IIRC the @{ } is just placeholders.. but I may be wrong?
The @{} are not placeholders, this is called a hashtable in PS. You are returning a hash-literal object. Unless you know you need it, the rule of thumb is to append -NoTypeInformation to Export-Csv. This behavior is now default in PSCore (v6+), and it will default to NoTypeInformation.
What do I need to supply for syntax for my Export-Csv? Currently, it exports a file with the proper file name and a .csv extension but it contains
Export-Csv expects headers in the form of properties. This must be present in the pipeline or -InputObject you are exporting. In my example, you see the header is inherited from the NoteProperty "UncShare" i declared in my PSCustomObject.

[/quote]

Aah, so by me deleting the headers it’s outputting “\@{10.0.3.4=10.0.3.115}\C$” with the IP first? 10.0.3.4 is the first IP, so it treats that as the header? That makes sense.

This is very helpful! Your illustration makes this much easier to understand. I’ll take a whack at this and pull up some more man files with the code. I’ll ultimately be appending multiple folder names to use as exclusions and such, so this will be a nice project.

 

Thanks again!

[quote quote=155958]Well there’s lots here to comment on but understandable since you’ve said you’re quite new to this. Seems like you’ve dived straight into solving an issue without covering a lot of the basics so if this is something you’re going to pursue I definitely recommend looking into courses from Pluralsight and Microsoft (I believe Microsoft Vitual Academy has been replaced with something else now? Not sure…)

To answer your questions first:

  1. You seem to have placed Export-Csv on a new line, but seemingly your intention was to pass the data from the line before to Export-Csv. Because it's on its own line and no pipeline characters at the end of the line before, PS interprets this command on its own. It's asking for a value for -InputObject as this is a required parameter in the default parameter set for Export-Csv. To correct this you should simply place a pipeline character at the end of the line before Export-Csv.
  2. This is a bit long-winded to explain... Firstly, you're using Import-Csv to read in your data, but from your example it seems the data is simply a list of IP addresses, one per line, with no header. Import-Csv expects a properly formatted, delimited file, including headers (by default). It reads in the data and creates objects with properties and values. In this case it sees the first IP in the list as the header and makes that a property name on the output object. What you've done after using Import-Csv is to create a string value using concatenation: ForEach-Object{'\\' + $_ + '\C$'}. $_ represents the current object in the pipeline, which will be the objects output from Import-Csv. In this instance you're converting the object to a string essentially through your use of concatenation with the + operator. In PS typically when you convert an object into a string the output is displayed as a representation of a property, value pair, eg @{property=value}. Therefore you end up with a string that is '\\', concatenated with the string representation of the object ($_ represents @{property=value}, concatenated with '\C$'.
  3. Export-Csv would not have done anything without having entered a value for -InputObject as it's asked for (see my response to 1), and you've not said what you've entered in the console when prompted, so, based on the output file I can only assume you simply typed something into the console when prompted (just text input), and because Export-Csv expects an object, the info being output is the properties of a string object, as would be from you entering simple text at the prompt.
To get what you want is fairly simple. If you have file.txt (a list of IP addresses, one per line) and your goal is to simply modify that text into a format you require:
PowerShell
6 lines
<textarea class="ace_text-input" style="opacity: 0; height: 18px; width: 6.59781px; left: 44px; top: 0px;" spellcheck="false" wrap="off"></textarea>
1
2
3
4
5
6
$Output = Get-Content C:\file.txt | ForEach-Object {"\\$_\C$"}
$Output -join ";" | Out-File C:\Output.txt
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Get-Content over Import-Csv since you seem to have a simple list of values rather than a properly formatted CSV file. Pipe to ForEach-Object to create the string output you require with each item from your input list. That is all assigned to a variable called $Output, then the next line uses the -join operator to join each item with a semicolon, then pipe to Out-File to generate your desired output file.

Hope this helps.

[/quote]

Aha, so I could have done this in a simpler form from the beginning. I realized last night while waiting for moderation approval that Export-Csv was basically telling me ‘What do you want me to put in here?!’. Was having a bit of an issue storing the appended data to a new variable and inevitably ran out of time at work. I’ll be cracking at it again this morning!

 

I found a PowerShell 5 course on Coursera that I’m going to start taking on lunches today because PS is just fascinating. Should get me the basics and then I can look up the differences in PS5 and PS6. I’ll check out the Microsoft Academy as well.

 

Thanks for the help! This will get me going on the initial part of this project.