Csv diff using powershell and showing (highlighting) changes on the new file - powershell

I have two csv files i need to compare them, then output a new file that will have the new values of the prophetess that changes and will mark(highlight) those properties some how. I already have the resulting file with all the values and all the properties but i dont know how to mark the specific properties that changed. Is there a way to do that is powershell?
Here is a sample of my code:
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
$file1,
[Parameter(Mandatory=$true)]
$file2
)
$content1 = Import-Csv -Path $file1
$content2 = Import-Csv -Path $file2
$props = $content1 | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
$comparedLines = Compare-Object $content1 $content2 -Property $props -PassThru | Where-Object {$_.SideIndicator -eq "=>" }
$comparedLines | Export-csv -Path C:\FullPUF\Difference.csv –NoTypeInformation

So, if I understand this correctly, $content2 is the newer file, right?
If so, then $comparedlines is going to contain all of the values which changed. If that's right, then we're in business, because Doug Finke wrote an absolutely awesome PowerShell module called importExcel that is going to make this trivially easy. But first, how did I do this?
I needed some files to test against, and I didn't have your source file so I couldn't guess at the values. I just made a simple CSV with a Name and Position value, and changed the Position numbers between Content1 and Content2.
How to solve this problem, first off, download Import-Excel right now. If you're on PowerShell version 4.0 or higher you can install it from PowerShell like so:
Find-Module ImportExcel | Install-Module
This module has the concept of ConditionalText filter rules. You can create a new one like this.
1..5 | Export-Excel C:\temp\test.xslx -Show`
-ConditionalText (New-ConditionalText -ConditionType GreaterThan 3)
This will output and display a new spreadsheet with the numbers 1 through 5 in it, and highlight the ones higher than 3.
We can also highlight rows that ContainsText which matches a value we know.
So, we take the value of $comparedLines using ForEach-Object, and create a New-ConditionalText rule to highlight the line if it contains one of the properties.
$highlight =$comparedLines | % {New-ConditionalText -ConditionalType ContainsText $_.Name}
Next, we will echo the contents of $content2, and use Export-Excel to create a new .xslx file and apply a conditional formatting rule to it.
$content2 | Export-Excel r:\test.xlsx -show -ConditionalText ($highlight)
And the output
You'll probably need to play with the code a tiny bit, and modify it to fit whatever your columns are called, but this is how you can export a csv and highlight the differences using PowerShell. Except there's no such thing as highlighting or text format in a .csv so you have to use an Excel SpreadSheet instead.
Lemme know if you need me to dig deeper anywhere :)

Related

Search for files containing specific numbers with Powershell

I have a list of file Id's
and I want to find the system feed files containing any of these numbers from a vast directory using powershell.
I was using Get-Content Cash* -totalcount 1 > cash_Check_outputfile.txt
but as each file contains numerous headers this was not working as I hoped.
Can anyone point me in the right direction?
Much appreciated.
Use the Get-ChildItem cmdlet to retrieve all files and use the Select-String cmdlet to find the files containing any number within your dictionary ($test in this example). Finally, use the Select-Object cmdlet to get the path.
$test = #(
707839
709993
)
$pathToSearch = 'C:\test'
Get-ChildItem $pathToSearch | Select-String $test | Select-Object -ExpandProperty Path

Dynamic replacement of strings from import-csv

I have a csv file that contains fields with values that begin with "$" that are representative of variables in different powershell scripts. I am attempting to import the csv and then replace the string version of the variable (ex. '$var1') with the actual variable in the script. I have been able to isolate the appropriate strings from the input but I'm having difficulty turning the corner on modifying the value.
Example:
CSV input file -
In Server,Out Server
\\$var1\in_Company1,\\$var2\in_Company1
\\$var1\in_Company2,\\$var2\in_Company2
Script (so far) -
$Import=import-csv "C:\temp\test1.csv"
$Var1="\\server1"
$Var2="\\server2"
$matchstring="(?=\$)(.*?)(?=\\)"
$Import| %{$_ | gm -MemberType NoteProperty |
%{[regex]::matches($Import.$($_.name),"$matchstring")[0].value}}
Any thoughts as to how to accomplish this?
The simplest way to address this that I could think of was with variable expansion as supposed to replacement. You have the variables set in the CSV so lets just expand them to their respective values in the script.
# If you dont have PowerShell 3.0 -raw will not work use this instead
# $Import=Get-Content $path | Out-String
$path = "C:\temp\test1.csv"
$Import = Get-Content $path -Raw
$Var1="\\server1"
$Var2="\\server2"
$ExecutionContext.InvokeCommand.ExpandString($Import) | Set-Content $path
This will net the following output in $path
In Server,Out Server
\\\\server1\in_Company1,\\\\server2\in_Company1
\\\\server1\in_Company2,\\\\server2\in_Company2
If the slashes are doubled up here and you do not want them to be then just change the respective variable values in your script of the data in the CSV.
Caveat
This has the potential to execute malicious code you did not mean too. Have a look at this thread for more on Expanding variables in file contents. If you are comfortable with the risks then this solution as presented should be fine.
Maybe I misunderstood, but do you need this?
$Import=import-csv "C:\temp\test1.cvs"
$Var1="\\server1"
$Var2="\\server2"
Foreach ($row in $Import )
{
$row.'In Server' = ($row.'In Server' -replace '\\\\\$var1', "$var1")
$row.'Out Server' = ($row.'Out Server' -replace '\\\\\$var2', "$var2")
}
$import | set-content $path

Using duplicate headers in Powershell .csv file

I have a .csv file and I want to import it into powershell then iterate through the file changing certain values. I then want the output to append to the original .csv file, so that the values have been updated.
My issue is that the .csv file has headers which aren't unique, and can't be changed as then it won't work in another program. Originally I defined my own headers in the powershell to get around this but then the output file has these new headers when it needs to have the old ones.
I have also tried ConvertFrom-Csv which means I can no longer access the columns I need to, so lots of runtime errors.
What would be ideal is to be able to use the defined column headers and then convert back to the original column headers. My current code is below:
$csvfile = Import-Csv C:\test.csv| Where-Object {$_.'3' -eq $classID} | ConvertFrom-Csv
foreach($record in $csvfile){
*do something*}
$csvfile | Export-Csv -path C:\test.csv -NoTypeInformation -Append
I've searched the web now for some hours and tried everything I've come across, to no avail.
Thanks in advance.
This is a somewhat hackish implementation but should work.
Remove all the headers as a single line and save it somewhere
Parse the new result-set (with the headers removed)
Add the line at the top when you are finished
A CSV is a comma delimited file, you don't have to treat it like structured data. Feel free to splice and dice as you want.
Since you know beforehand how many columns are in the input CSV file, you can import without the header and process internally. Example:
$columns = 78
Import-Csv "inputfile.csv" -Header (0..$($columns - 1)) | Select-Object -Skip 1 | ForEach-Object {
$row = $_
$outputObject = New-Object PSObject
0..$($columns- 1) | ForEach-Object {
$outputObject | Add-Member NoteProperty "Col$_" $row.$_
}
$outputObject
} | Export-Csv "outputfile.csv" -NoTypeInformation
This example generates new PSObjects and then outputs a new CSV file with generic column names (Col0, Col1, etc.).

PowerShell Out-file manipulation

i hope someone can help.
I am trying to manipulate a file created by powershell.
I managed to get to the end result that i want, but i am sure it would be easier if it was only one command.
# Invoke the Exchange Snapping ( make sure you are Exchange Admin to do it SO)
add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010
#Create a file with list of DL in the organization
Get-DistributionGroup | Select-Object Name | Out-File C:\Pre_DLGroups.txt
$content = Get-Content C:\Pre_DLGroups.txt
#Remove the 3 first lines of the file that you dont need it
$content | Select-Object -Skip 3 | Out-file C:\DLGroups.txt
#Trim the space in the end and crate the Final file
Get-Content C:\DLGroups.txt | Foreach {$_.TrimEnd()} | Set-Content c:\FinalDLGroup.txt
is that way to make the end result in a single file rather than creating 3?
cheers
Elton
You can send your content across the pipeline without writing it out to files. You can use parenthesis to group the output of certain sets of cmdlets and/or functions, and then pipe that output through to the intended cmdlets.
This can all be applied on a single line, but I've written it here on multiple lines for formatting reasons. The addition of Out-String is something of a safety measure to ensure that whatever output you're intending to trim can actually be trimmed.
Since we're not getting this content from a text file anymore, powershell could possibly return an object that doesn't understand TrimEnd(), so we need to be ready for that.
(Get-DistributionGroup | Select-Object Name) |
Out-String |
Select-Object -Skip 3 |
Foreach {$_.TrimEnd()} |
Set-Content c:\FinalDLGroup.txt
However, an even smaller solution would involve just pulling each name and manipulating it directly. I'm using % here as an alias for Foreach-Object. This example uses Get-ChildItem, where I have some files named test in my current directory:
(Get-ChildItem test*) |
% { $_.Name.TrimEnd() } |
Set-Content c:\output.txt
Get-DistributionGroup |
Select-Object -ExpandProperty Name -Skip 3 |
Set-Content c:\FinalDLGroup.txt

Get-ChildItem file/folder

I am trying to let Get-ChildItem retrieve the contents of a folder, and show the size of each object in the folder, the name and the type of object (file/directory). I am however having trouble getting only those three columns to work.
The name and length are rather straightforward, but how do I display differences between files and folders?
Check the PSIsContainer property. It is set to $true for folders and $false for files. Here's an example:
Get-ChildItem | Foreach-Object{
New-Object PSObject -Property #{
Name = $_.Name
SizeMB = if($_.PSIsContainer) { (Get-ChildItem $_.FullName -Recurse | Measure-Object Length -Sum).Sum/1mb } else {$_.Length}
Type = if($_.PSIsContainer) {'Directory'} else {'File'}
}
}
I believe that this is possible by taking the 'Mode' information. ( See this answer here )
Basically, then, anything listed by the Get-ChildItem command whereby the 'Mode' begins with "d".
Here's the actual meanings of the 6 possible values in 'Mode', if you didn't want to go to #Joey's answer:
In any case, the full list is:
d - Directory
a - Archive
r - Read-only
h - Hidden
s - System
l - Reparse point, symlink, etc.
So I've used this to output a CSV, which I'll then flag the folders in excel, or my Flow, or SharePoint. The command I've used is:
Get-ChildItem -Recurse | Select-Object DirectoryName, BaseName, Extension, Mode | Export-Csv -Path INSERTPATH\listings.csv -Encoding ascii -NoTypeInformation
Hope that this helps anyone that comes across it.
Caveat, this is first time that I'm answering with the full intent of answering. I believe that even though this is 6 years old, people will still find it useful when trying to achieve the same thing.