I don't understand using get-content on a csv - powershell

How come when I do (Get-Content $CSV1)[2] in the Power-shell console on any .csv file I get the field but when I do it in the ISE I get errors like this.
$CSV1 = Import-Csv "C:\Users\Administrator\Documents\lab8\usersF.csv"
(Get-Content $CSV1)[2]
usersF.csv contents
GivenName
Ylnum
Dexcd
Igbos
Rzjlr
Errors
Cannot index into a null array.
At C:\Users\Administrator\Documents\lab8\ovie_lab7_merged.ps1:5 char:1
+ (Get-Content $CSV1)[2]
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
I've tried the solution #TheIncorrigible1 gave me and it worked, but now I'd like to export that data to a .csv and instead of the string I got the string length in the .csv file how can I fix this?
$CSV1 = Import-Csv -Path "C:\Users\Administrator\Documents\lab8\usersF.csv"
$test = $CSV1.GivenName[4]
$test | Export-Csv "C:\Users\Administrator\Documents\lab8\test.csv"
#TYPE System.String
Length
5

So the problem you're running into is a simple type understanding problem.
Import-Csv takes the Path you provide to it and imports that into a PSCustomObject. You're trying to Get-Content -Path [PSCustomObject], but that is not a supported type for the -Path argument (if you read the help topic, it expects a [String[]]).
If you want that first line, you should do something like:
$Path = 'C:\Users\Administrator\Documents\lab8\usersF.csv'
#(Get-Content -Path $Path)[1] #Arrays are zero-indexed
Alternatively,
$Csv = Import-Csv -Path $Path
$Csv.GivenName[0]
To address your edit, you aren't calling Export-Csv properly. It expects a PSCustomObject, but you're passing it a single string. I'd suggest using Out-File instead.
$CSV1 = Import-Csv -Path C:\Users\Administrator\Documents\lab8\usersF.csv
$test = $CSV1.GivenName[4]
$test |
OutFile -FilePath C:\Users\Administrator\Documents\lab8\test.csv

Related

How do I write a script to reboot a list of servers, but will EXCLUDE servers I don't want rebooted?

Being new to PowerShell I've been following some of the guidance in these posts to write a script for what's mentioned in the subject.
Here's the script:
Get-Content -Path C:\temp\Domain.txt | Restart-Computer -force | Where-Object { $._Name -notmatch "^(SERVER01)"}
Here's the error:
Restart-Computer : Cannot validate argument on parameter 'ComputerName'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At line:1 char:40
+ ... et-Content -Path C:\temp\Domain.txt | Restart-Computer -force | Where ...
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:PSObject) [Restart-Computer], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RestartComputerCommand
For reference, the DOMAIN.txt has a list of servers that will periodically change so I want to skip certain servers should they end up on the list.
The error simply means you have an empty line on your text file, you can filter the lines using .Where(..) method and exclude empty or white space lines with the help of [string]::IsNullOrWhiteSpace(..) method. I have changed -notmach for the containment operator -notin.
Note, -notin looks for an exact match within the collection $hostsToExclude.
$hostToExclude = 'server1', 'server2'
(Get-Content -Path C:\temp\Domain.txt).Where({
-not [string]::IsNullOrWhiteSpace($_) -and $_ -notin $hostToExclude
}) | Restart-Computer -Force
It's worth noting that, on your snippet, you're restarting the hosts before filtering the collection. Get-Content should be followed by Where-Object.

how to append output to a CSV file

foreach ( $newfile in $file )
{
$b = Get-CMDeploymentStatus -PackageId $newfile -StatusType Any | select PackageID
Write-Output $b | Export-Csv -Path "C:\Users\PSM-6A1A000000000000\Documents\list.csv"
}
I am giving input to this with an input file which has number of package names listed and then I want to process it in such a way that the output comes one after the other right now I am getting an error as
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null. At line:16 char:20 + Write-Output $b | Export-Csv -Path "C:\Users\PSM-6A1A000000000000\Documents\lis ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand
Your code is assuming that you will have a result coming back from $b, if it does not though, you'll get an error because you're piping $b, which is null, into Export-CSV.
$null |export-csv c:\temp\1.csv
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
At line:1 char:8
+ $null |export-csv c:\temp\1.csv
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCs
You should add a 'Guard Clause' before you try to export.
if ($null -ne $b){
Export-csv -Append -InputObject $b
}
At least this will continue executing. Now your next problem is to determine why $b would be empty...from my experience with CM, I bet you need to specify which property in your $file you need. Maybe that line should read:
$b = Get-CMDeploymentStatus -PackageId $newfile.PackageId -StatusType Any | select PackageID
Since you say "I am giving input to this with an input file which has number of package names listed", but your code uses PackageId..
It looks to me that this file contains a packageId, each on a single line.
Anyway, I don't see the code ever reading this file..
If my assumption about the text file is correct, try:
# read the content of the text file and loop through the lines
# collect the output from Get-CMDeploymentStatus in variable $result
$result = Get-Content -Path 'X:\TheFileWithPackageIds.txt' | ForEach-Object {
# inside the ForEach-Object, the $_ automatic variable represents a single line from the text file
Get-CMDeploymentStatus -PackageId $_ -StatusType Any | select PackageID
}
# output on screen
$result
# write to new CSV file
$result | Export-Csv -Path "C:\Users\PSM-6A1A000000000000\Documents\list.csv" -NoTypeInformation

beginner Powershell Script Error

To load a text file of 3 ip addresses comma separated values, into an array, and then have the contents in the array changed for every 3rd octet of the ip address, and then exported back to a csv or text file.
##load file to an array
$ipFileName="C:\Users\HarmanGrewal\Google Drive\win213\assignment2\IP.txt"
$array1=#()
$array1=Get-Content $ipFileName -Delimiter ","
#now we have the contents in an array
$count=0
foreach($i in $array1){
$array1[$count] = $array1[$count] -replace "\.\d{1}\.",".2."
$count++
}
Get-Content $array1 | export-csv -path "C:\Users\HarmanGrewal\test.txt"
A successful exportation of data to a csv file.
An empty csv file instead.
Get-Content : Cannot find path 'C:\Users\HarmanGrewal\192.168.2.10,' because it does not exist.
At C:\Users\HarmanGrewal\Google Drive\win213\assignment2\assignment2QuestionAnswer1.ps1:13 char:1
+ Get-Content $array1 | export-csv -path "C:\Users\HarmanGrewal\test.tx …
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\HarmanGrewal\192.168.2.10,:String) [Get-Content], ItemNotFound Exception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
Get-Content : Cannot find path 'C:\Users\HarmanGrewal\192.168.2.14,' because it does not exist.
At C:\Users\HarmanGrewal\Google Drive\win213\assignment2\assignment2QuestionAnswer1.ps1:13 char:1
+ Get-Content $array1 | export-csv -path "C:\Users\HarmanGrewal\test.tx …
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\HarmanGrewal\192.168.2.14,:String) [Get-Content], ItemNotFound Exception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
Get-Content : Illegal characters in path.
At C:\Users\HarmanGrewal\Google Drive\win213\assignment2\assignment2QuestionAnswer1.ps1:13 char:1
+ Get-Content $array1 | export-csv -path "C:\Users\HarmanGrewal\test.tx …
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (C:\Users\HarmanGrewal\192.168.2.15:String) [Get-Content], ArgumentException
+ FullyQualifiedErrorId : ItemExistsArgumentError,Microsoft.PowerShell.Commands.GetContentCommand
Get-Content : Cannot find path 'C:\Users\HarmanGrewal\192.168.2.15' because it does not exist.
At C:\Users\HarmanGrewal\Google Drive\win213\assignment2\assignment2QuestionAnswer1.ps1:13 char:1
+ Get-Content $array1 | export-csv -path "C:\Users\HarmanGrewal\test.tx …
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\HarmanGrewal\192.168.2.15:String) [Get-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
# Read the 3 IP addresses from the input file into an array.
# .TrimEnd() ensures that a trailing newline, if any, is stripped (syntax requires PSv3+)
$ips = (Get-Content $ipFileName -Delimiter ",").TrimEnd()
# Replace single-digit IP octets with fixed value 2,
# join the resulting IPs with ',' again, and write to an output file.
$ips -replace '\.\d{1}\.', '.2.' -join ',' | Set-Content "C:\Users\HarmanGrewal\test.txt"
As for what you tried:
$array1=#()
$array1 = ...
$array1=#() is pointless, because the next line assigns to $array1 again, which means that its RHS determines the data type of $array1, irrespective of the previous =#() assignment;
if the Get-Content command happens to return a single value, $array1 will be a scalar; you could prevent that by enclosing the Get-Content command in #(...), the array-subexpression operator, but in PSv3+ that is generally not necessary, due to its unified handling of scalars and collections.
foreach($i in $array1) enumerates the array elements themselves, where $i is a by-value copy of each array element.
Instead of using a separate $count variable to access the elements by reference via their index in order to update them, PowerShell allows you to simply recreate the array as a whole:
$array1 = foreach ($el in $array1) { $el -replace "\.\d{1}\.",".2." }
or, more concisely, relying on the -replace operator's support for array-valued LHS values:
$array1 = $array1 -replace "\.\d{1}\.",".2."
As Harsh Jaswal's answer points out, Get-Content $array1 mistakenly passes intended file contents, whereas what Get-Content expects are filename arguments to read contents from.
Since the values to output - in array $array1 - are already in memory, you can simply send them through the pipeline directly.
Export-Csv operates on the properties of an object, and since you're supplying string objects that only have a .Length property, all that will be exported is that property, which is not the intent.
In the case at hand you have to write a text file directly, using Set-Content, based on constructing CSV-format strings in memory.
Note that Set-Content uses the system's legacy "ANSI" code page by default; use -Encoding <encodingName> to change that.
The first thing is if you are using foreach here then there is no need of $count variable. And the second thing is in your last line you are passing collection $array1 to Get-Content. It takes the path as a parameter. So it is trying to get the contents of the file stored at $array1, which is not correct.
Please modify the code as below.
$ipFileName="C:\Users\HarmanGrewal\Google Drive\win213\assignment2\IP.txt"
$array1=#()
$array1=Get-Content $ipFileName -Delimiter ","
#now we have the contents in an array
foreach($i in $array1){
$i = $i -replace "\.\d{1}\.",".2."
$i
}
$array1 | export-csv -path C:\Users\HarmanGrewal\test.txt

Rename a list of files

I need to rename all files below pwd named all_v4_0.csv to all_v4_1.csv.
So far, I have worked my way to this piece of PowerShell:
$oldfiles = dir -recurse | ?{$_.Name -eq "all_v4_0.csv"}
foreach ($o in $oldfiles) {
$o.CopyTo Join-Path $o.Directory.ToString() "all_v4_1.csv"
}
But the foreach loop fails with the message that
At line:2 char:15
+ $o.CopyTo Join-Path $o.Directory.ToString() "all_v4_1.csv"
+ ~~~~~~~~~
Unexpected token 'Join-Path' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
What am I doing wrong here?
Update, 20150604
As commented below by Manuel Batsching, the original version can be fixed by adding two layers of parentheses: one to indicate function argument, and one to force evaluation order:
$oldfiles = dir -recurse | ?{$_.Name -eq "all_v4_0.csv"}
foreach ($o in $oldfiles) {
$o.CopyTo((Join-Path $o.Directory.ToString() "all_v4_1.csv"))
}
For the problem at hand, one of the solutions with .FullName.Replace would probably be easier.
PSH's parser is not reading the Join-Path and its arguments as an expression to evaluate and pass result to outer expression. So parentheses to force evaluation order.
But additionally CopyTo is a .NET member, rather than a PSH cmdlet, so it needs to have parentheses around its argument (and no space).
Thus:
$o.CopyTo((Join-Path $o.Directory.ToString() "all_v4_1.csv"))
(Possibly using PSH's Copy-Item cmdlet would be a cleaner option.)
Set the target name separately before doing the copy. The below should work:
$oldfiles = dir -recurse | ?{$_.Name -eq "all_v4_0.csv"}
foreach ($o in $oldfiles) {
$newName = $o.FullName.replace("all_v4_0.csv","all_v4_1.csv")
Copy-Item $o.FullName $newName
}
If you want to keep things simple you can also use string concatenation to create the target path.
Get-ChildItem -Recurse -Include 'all_v4_0.csv' |
ForEach { $_.MoveTo($_.Directory.FullName + '\all_v4_1.csv') }
Simply replace the substring in the new name of the files:
Get-ChildItem -Recurse -Include 'all_v4_0.csv' |
Rename-Item -NewName { $_.Name.Replace('4_0', '4_1') }

Path variable does not seem to be consistent in a single Powershell script

I'm running what I think is a relatively simple script:
$txtPath = "c:\users\xxxxxx\desktop\cgc\tx\"
$srcfiles = Get-ChildItem $txtPath -filter "*.txt*"
ForEach($txtfile in $srcfiles) {
Write-Host $txtfile
Get-Content $txtfile
}
and I get the following output:
Automatic_Post-Call_Survey_-_BC,_CC.txt
Get-Content : Cannot find path 'C:\users\x46332\desktop\cgc\Automatic_Post-Call_Survey_-_BC,_CC.txt' because it does no
t exist.
At C:\users\x46332\desktop\cgc\testcount2.ps1:34 char:13
+ Get-Content <<<< $txtfile
+ CategoryInfo : ObjectNotFound: (C:\users\x46332...ey_-_BC,_CC.txt:String) [Get-Content], ItemNotFoundEx
ception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
This is the output from Write-Host $txtfile followed immediately by Get-Content $txtfile and get-content seems to be the heart of my issue.
When I comment out the Get-Content line, the script generates a list of the filenames to the console. This suggests to me that the $txtPath is properly defined. However, I add Get-Content for the SAME file/same variable and for some reason, the \tx portion of the path disappears from the search string. My filename prints, but then Get-Content can't find the path for the filename is just printed.
I suspect that the "directory doesn't exist" error isn't really that the directory doesn't exist. So what should I be looking at? There's not a lot of space in my code for an error to hide, but I can't find it...thoughts?
Get-Content needs the full path e.g.:
Get-Content $txtFile.FullName
When you specify Get-Content $txtFile, PowerShell attempts to coerce the argument $txtFile to the required argument Path and to do so, it coerces the FileInfo object to a string. This process yields just the name of the file.
Another way to do this is:
$txtFile | Get-Content