appending different data to the end of each line in csv file - powershell

I need to add text to the end of the header in a text/csv file and then add other text (date) at the end of each line below the header. Adding the text part is working fine but it's the exporting to a csv that's not working as expected.
The expected output is (bold text is the added text);
"Folder Name","Files","Folders","Size","Comment","ReportDate"
"\\server\share\folder","2,029,756","819,527","1,785,490,958,735"," ","1/10/2020"
Instead I'm getting;
"Length"
"61"
"74"
"88"
"118"
$Path = "C:\temp\"
$files = Get-ChildItem $Path -filter '*.csv'
ForEach ($file in $files)
{
$datetmp = $file.PSChildName.Substring(0,10)
$datetmp = $datetmp.split("_")
$date = $datetmp[1] + "/" + $datetmp[2] + "/" + $datetmp[0]
$Fullpath = $Path + $file
[System.Collections.ArrayList]$content = Get-Content $Fullpath #| %{"$_," + $date}
$rptinsert = #()
for ($i=0; $i -lt ($content.Count); $i++)
{
if ($i -eq 0)
{
$rptinsert += $content[$i] + ",""ReportDate"""
}
else
{
$rptinsert += $content[$i] + ",`"$date`""
}
}
$Report = $Path + $file.PSChildName.Substring(0, 10) + "-FileSizes2.csv"
$rptinsert | Export-Csv -path $Report -Encoding ascii -NoTypeInformation
}
I'm sure there are shorter methods to perform the some of my lines as well, just not looking for that right now. ;-)

To use Export-Csv the way you are expecting, you need to be inputting objects with property/value pairs. You are piping in strings. The only property a string has is Length. I would use Import-Csv to read the files, modify the returned values, and then Export-Csv to output the changed objects. Below is a blueprint that will work:
$Path = "C:\temp\"
$files = Get-ChildItem $Path -filter '*.csv'
Foreach ($file in $files) {
$datetmp = $file.Name.Substring(0,10).Split('_')
$date = $datetmp[1],$datetmp[2],$datetmp[0] -join '/'
$content = Import-Csv $file | Add-Member -MemberType NoteProperty -Name 'ReportDate' -Value $date -PassThru
$content | Export-Csv -Path ($Path + $file.Name.Substring(0, 10) + "-FileSizes2.csv") -NoType
}
The output of Import-Csv is a collection of custom objects with property names that match the header line of the CSV file. Since it appears you want the same value added to every line of a CSV file, you can just run one Add-Member command. If each line needs a different value, then you will need to loop through each line and run an Add-Member command.
Add-Member allows for adding different member types to an object. In your case, you want to add a NoteProperty type with a value.
Once the updates are complete to one CSV's contents, you can pipe those results into Export-Csv. -NoType prevents an additional header line with type information from the output.

Related

Grabbing MetaData and outputting to XML

I'm trying to get the script to read the first line of files.txt, grab the data metadata requested and then output the .xml, move onto the next line and repeat.
I expect each line to have its own individual file with the meta data and then the next line to do the same.
Currently it creates all the individual files, but the data is combined and duplicated across them.
The files.txt contains the full path and files that is being
collected with the metadata e.g.
D:\data\testscript.ps1
D:\data\workingfile.doc
C:\Windows\temp\output.txt
Filesv2.txt contain the filename of the xml output and is consistent
in array with files.txt e.g
D_data_testscript.ps1
D_data_workingfile.doc
C_Windows_temp_output.txt
$logdir = "C:\Users\gnome\Documents"
$inputPath = Get-Content -Path "C:\Users\gnome\Documents\files.txt"
$inputSave = Get-Content -Path "C:\Users\gnome\Documents\filesv2.txt"
#Get-*
$hash = Get-FileHash -Path $inputPath
$acl = Get-Acl -Path $inputPath | Select-Object *
$metadata = Get-ChildItem -Path $inputPath | Select-Object *
#Loop each directory in $inputPath
#ForEach ($path in $inputPath){
$output = ForEach ($path in $inputPath){
Write-host Checking $path
ForEach($inputSave in $inputSave){
#{
#$log = "$logdir\$inputSave.xml"
sha256Hash = $hash
acl = $acl
metadata =$metadata
}
$output | Export-Clixml "$logdir\test1_$inputSave.xml"
}
}
'''
From your comment, files.txt stores full path and filenames and filesv2.txt has new names for these files according to some naming convention to be used for the output xml filename.
Having both arrays separate from eachother in separate files is somewhat accident-prone, because all that links the file name to the convention name is the index in both arrays..
Below first creates a Hashtable from these arrays assuming the indices match and both arrays have the same number of elements
$logdir = "C:\Users\gnome\Documents"
$inputPath = #(Get-Content -Path "C:\Users\gnome\Documents\files.txt") # full path and filenames
$inputSave = #(Get-Content -Path "C:\Users\gnome\Documents\filesv2.txt") # naming convention for the output
# create a Hashtable where the input from files.txt is key and the naming convention for the output xml is value
$filesHash = #{}
for ($i = 0; $i -lt $inputPath.Count; $i++) {
$filesHash[$inputPath[$i]] = $inputSave[$i]
}
# now iterate
$filesHash.GetEnumerator() | ForEach-Object {
Write-host Checking $_.Key
$output = [PsCustomObject]#{
sha256Hash = Get-FileHash -Path $_.Key -Algorithm SHA256
acl = Get-Acl -Path $_.Key
metadata = Get-Item -Path $_.Key
}
$outFile = Join-Path -Path $logdir -ChildPath ('{0}.xml' -f $_.Value)
$output | Export-Clixml -Path $outFile
}

Trimming the file path in a CSV up to a certain path/file name stored in a variable

I have a PowerShell script that stores the full paths of the files in a specific directory along with some other information. I have exported the CSV file. Now, the paths are actually being combined together to comprise of the full path. Let me give an example below:
$root= C:\Users\home\
$web = facebook website\domain
$app = facebook android\latest
These paths are then joined together with either Join-Path or $fbweb = $root + $web to make up the full path: C:\Users\home\facebook website\domain
Now the above mentioned path will have other files, subfolders etc in it but that's the gist of how the paths are structured. I have exported them in the CSV file but I'm having trouble with the following. I need the CSV file to have paths in such a way that the part leading up to the $web is trimmed out.
For instance if the CSV file is like this:
Path
C:\Users\home\facebook website\domain\version\version-feb-2020.txt
C:\Users\home\facebook website\domain\interface\somefile.html
C:\Users\home\facebook android\latest\messenger\messenger app files\code.js
C:\Users\home\facebook android\latest\application\somecode.js
I want it to turn out like this:
Path
facebook website\domain
\version\version-feb-2020.txt
\interface\somefile.html
facebook android\latest
\messenger\messenger app files\code.js
application\somecode.js
I have tried using the following to trim it out:
$number = [regex]::matches($fbweb,"\\").count
Select-Object Hash,
#{
Name = "FilePath";
Expression = { [string]::Join("\", ($_.Path -split "\\" | Select-Object -skip ($number)))}
}
Update:
I have tried this:
$replace = Join-Path -Path $root -ChildPath $web
echo $replace
$RefHash = Import-csv "C:\Users\Admin\Desktop\fb.csv"
$RefHash | ForEach-Object {
echo $_.Path
($_.Path).Replace($replace, "\")
} | Export-csv "C:\Users\Admin\Desktop\replaced.csv"
But this just results in the exported csv showing the following:
#TYPE System.String
"Length"
"numbers"
"numbers"
"numbers"
As discussed, you have 2 methods to manage this:
Treat the csv file as a text file and do a replace on a get-content:
(Get-Content -Path "C:\temp\TestMD5.csv").Replace($replace, "\") | Set-Content "C:\temp\TestMD5updated.csv"
Import the CSV, separate the each of the parameters, modify what you require and then build a pscustomobject which you then export as csv:
#Preparing variables
$scriptdir = [System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Path)
$sourcecsv = Import-csv -path "C:\temp\TestMD5.csv"
$obj = #()
$root = "C:\Temp"
$web = "Test01\Test02\"
$replace = Join-Path -Path $root -ChildPath $web
$target = "\"
#Executing replace
foreach ($line in $sourcecsv) {
$object = New-Object -TypeName psobject
$algo = $line | Select-Object -ExpandProperty 'Algorithm'
$Hash = $line | Select-Object -ExpandProperty 'Hash'
$Path = ($line | Select-Object -ExpandProperty 'Path').Replace($replace, $target)
$object | Add-Member -MemberType NoteProperty -Name Algorithm -Value $algo
$object | Add-Member -MemberType NoteProperty -Name Hash -Value $Hash
$object | Add-Member -MemberType NoteProperty -Name Path -Value $Path
$obj += $object
$object
}
$obj | Export-Csv -NoTypeInformation -Path "$scriptdir\UpdatedVars.csv"
The first one is faster, the 2nd one provides you the flexibility that would allow you to build functions that are generalized and modify additional parameters as required.
OK assuming you don't actually need to import and deal with the file as a CSV file. You simply need to replace the strings in a text file. If so then you can use get-content instead of import-csv
You want to use REPLACE.
$SourceFile = Get-Content -Path "D:\URL.txt"
$root= "C:\Users\home\"
$web = "facebook website\domain"
$app = "facebook android\latest"
$replace1 = $root+$web
$replace2 = $root+$app
$SourceFile -replace [Regex]::Escape($replace1), "\" -replace [Regex]::Escape($replace2), "\" | Set-Content -Path "D:\urlreplaced.txt"
This will do the replace and output the new file to D:\urlreplaced.txt
To convert the csv data into a new format as you would like, you could do the following:
$root= 'C:\Users\home'
$web = 'facebook website\domain'
$app = 'facebook android\latest'
$webPath = [regex]::Escape((Join-Path -Path $root -ChildPath 'facebook website\domain'))
$appPath = [regex]::Escape((Join-Path -Path $root -ChildPath 'facebook android\latest'))
$data = Import-Csv -Path "C:\Users\Admin\Desktop\fb.csv"
$appData = ($data | Where-Object { $_.Path -match "^$appPath" } | Select-Object #{Name = 'Path'; Expression = {$_.Path -replace "^$appPath" }}).Path
$webData = ($data | Where-Object { $_.Path -match "^$webPath" } | Select-Object #{Name = 'Path'; Expression = {$_.Path -replace "^$webPath" }}).Path
# manually create the one-column csv (easiest is to do this in a Here-String)
$newData = #"
Path
$web
$($webData -join [Environment]::NewLine)
$app
$($appData -join [Environment]::NewLine)
"#
# output on screen
$newData
# output to new CSV file
$newData | Set-Content -Path "C:\Users\Admin\Desktop\replaced.csv" -Force
Output on screen
Path
facebook website\domain
\version\version-feb-2020.txt
\interface\somefile.html
facebook android\latest
\messenger\messenger app files\code.js
\application\somecode.js

How to parse csv file, look for trigger and split into new files with powershell

I have a CSV file which is structured like this:
"SA1";"21020180123155514000000000000000002"
"SA2";"21020180123155514000000000000000002";"210"
"SA4";"21020180123155514000000000000000002";"210";"200000001"
"SA5";"21020180123155514000000000000000002";"210";"200000001";"140000001";"ZZ"
"SA1";"21020180123155522000000000000000002"
"SA2";"21020180123155522000000000000000002";"210"
"SA4";"21020180123155522000000000000000002";"210";"200000001"
"SA5";"21020180123155522000000000000000002";"210";"200000001";"140000671";"ZZ"
"SA1";"21020180123155567000000000000000002"
"SA2";"21020180123155567000000000000000002";"210"
"SA4";"21020180123155567000000000000000002";"210";"200000001"
"SA5";"21020180123155567000000000000000002";"210";"200000001";"140000001";"ZZ"
So the Value in the second field (separator ';') marks the data which belongs together and value 140000001 or 140000671 is the trigger.
So the result should be:
1st file: 140000001.txt
"SA1";"21020180123155514000000000000000002"
"SA2";"21020180123155514000000000000000002";"210"
"SA4";"21020180123155514000000000000000002";"210";"200000001"
"SA5";"21020180123155514000000000000000002";"210";"200000001";"140000001";"ZZ"
"SA1";"21020180123155567000000000000000002"
"SA2";"21020180123155567000000000000000002";"210"
"SA4";"21020180123155567000000000000000002";"210";"200000001"
"SA5";"21020180123155567000000000000000002";"210";"200000001";"140000001";"ZZ"
2nd file: 140000671.txt
"SA1";"21020180123155522000000000000000002"
"SA2";"21020180123155522000000000000000002";"210"
"SA4";"21020180123155522000000000000000002";"210";"200000001"
"SA5";"21020180123155522000000000000000002";"210";"200000001";"140000671";"ZZ"
For now I found a snippet which splits the big file by the second field:
$src = "C:\temp\ORD001.txt"
$dstDir = "C:\temp\files\"
Remove-Item -Path "$dstDir\\*"
$header = Get-Content -Path $src | select -First 1
Get-Content -Path $src | select -Skip 1 | foreach {
$file = "$(($_ -split ";")[1]).txt"
Write-Verbose "Wrting to $file"
$file = $file.Replace('"',"")
if (-not (Test-Path -Path $dstDir\$file))
{
Out-File -FilePath $dstDir\$file -InputObject $header -Encoding ascii
}
$file -replace '"', ""
Out-File -FilePath $dstDir\$file -InputObject $_ -Encoding ascii -Append
}
For the rest I'm standing in the dark.
Please help.
The Import-CSV cmdlet will work here, if you don't already know about it. I would use that, as it returns all the rows as different objects in an array, with the properties being the column values. And you don't have to manually remove the quotes and such. Assuming the second column is a date time value, and should be unique for each group of 4 consecutive rows, then this will work:
$src = "C:\temp\ORD001.txt"
$dstDir = "C:\temp\files\"
Remove-Item -Path "$dstDir\*"
$csv = Import-CSV $src -Delimiter ';'
$DateTimeGroups = $csv | Group-Object -Property 'ColumnTwoHeader'
foreach ($group in $DateTimeGroups) {
$filename = $group.Group.'ColumnFiveHeader' | select -Unique
$group.Group | Export-CSV "$dstDir\$filename.txt" -Append -NoTypeInformation
}
However, this will break if two of those "groups of 4 consecutive rows" have the same value for the second column and the fifth column. There isn't a way to fix this unless you are certain that there will always be 4 consecutive rows in each time group. In which case:
$src = "C:\temp\ORD001.txt"
$dstDir = "C:\temp\files\"
Remove-Item -Path "$dstDir\*"
$csv = Import-CSV $src -Delimiter ';'
if ($csv.count % 4 -ne 0) {
Write-Error "CSV does not have a proper number of rows. Attempting to continue will be bad :)"
return
}
for ($i = 0 ; $i -lt $csv.Count ; $i=$i+4) {
$group = $csv[$i..($i+4)]
$group | Export-Csv "$dstDir\$($group[3].'ColumnFiveHeader').txt" -Append -NoTypeInformation
}
Just be sure to replace Column2Header and Column5Header with the appropriate values.
If performance is not a concern, combining Import-Csv / Export-Csv with Group-Object allows the most concise, direct expression of your intent, using PowerShell's ability to convert CSV to objects and back:
$src = "C:\temp\ORD001.txt" # Input CSV file
$dstDir = "C:\temp\files" # Output directory
# Delete previous output files, if necessary.
Remove-Item -Path "$dstDir\*" -WhatIf
# Import the source CSV into custom objects with properties named for the columns.
# Note: The assumption is that your CSV header line defines columns "Col1", "Col2", ...
Import-Csv $src -Delimiter ';' |
# Group the resulting objects by column 2
Group-Object -Property Col2 |
ForEach-Object { # Process each resulting group.
# Determine the output filename via the group's last row's column 5 value.
$outFile = '{0}\{1}.txt' -f $dstDir, $_.Group[-1].Col5
# Append the group at hand to the target file.
$_.Group | Export-Csv -Append -Encoding Ascii $outFile -Delimiter ';' -NoTypeInformation
}
Note:
The assumption - in line with your sample data - is that it is always the last row in a group of lines sharing the same column-2 value whose column 5 contains the root of the output filename (e.g., 140000001)
Sorry but I don't have a Header Column. It's a semikolon seperated txt file for an interface
You can simply read the file with Get-Content, and then search for the trigger in the line.
I hope this small example can help:
$file = Get-Content CSV_File.txt
$140000001 = #()
$140000671 = #()
$bTrig = #()
foreach($line in $file){
$bTrig += $line
if($line -match ';"140000001";'){
$140000001 += $bTrig
$bTrig = #()
}
elseif($line -match ';"140000671";'){
$140000671 += $bTrig
$bTrig = #()
}
}
if($bTrig.Count -ne 0){Write-Warning "No trigger for $bTrig"}
$140000001 | Out-File 140000001.txt -Encoding ascii
$140000671 | Out-File 140000671.txt -Encoding ascii

Using Powershell to replace multiple strings in multiple files & folders

I have a list of strings in a CSV file. The format is:
OldValue,NewValue
223134,875621
321321,876330
....
and the file contains a few hundred rows (each OldValue is unique). I need to process changes over a number of text files in a number of folders & subfolders. My best guess of the number of folders, files, and lines of text are - 15 folders, around 150 text files in each folder, with approximately 65,000 lines of text in each folder (between 400-500 lines per text file).
I will make 2 passes at the data, unless I can do it in one. First pass is to generate a text file I will use as a check list to review my changes. Second pass is to actually make the change in the file. Also, I only want to change the text files where the string occurs (not every file).
I'm using the following Powershell script to go through the files & produce a list of the changes needed. The script runs, but is beyond slow. I haven't worked on the replace logic yet, but I assume it will be similar to what I've got.
# replace a string in a file with powershell
[reflection.assembly]::loadwithpartialname("Microsoft.VisualBasic") | Out-Null
Function Search {
# Parameters $Path and $SearchString
param ([Parameter(Mandatory=$true, ValueFromPipeline = $true)][string]$Path,
[Parameter(Mandatory=$true)][string]$SearchString
)
try {
#.NET FindInFiles Method to Look for file
[Microsoft.VisualBasic.FileIO.FileSystem]::GetFiles(
$Path,
[Microsoft.VisualBasic.FileIO.SearchOption]::SearchAllSubDirectories,
$SearchString
)
} catch { $_ }
}
if (Test-Path "C:\Work\ListofAllFilenamesToSearch.txt") { # if file exists
Remove-Item "C:\Work\ListofAllFilenamesToSearch.txt"
}
if (Test-Path "C:\Work\FilesThatNeedToBeChanged.txt") { # if file exists
Remove-Item "C:\Work\FilesThatNeedToBeChanged.txt"
}
$filefolder1 = "C:\TestFolder\WorkFiles"
$ftype = "*.txt"
$filenames1 = Search $filefolder1 $ftype
$filenames1 | Out-File "C:\Work\ListofAllFilenamesToSearch.txt" -Width 2000
if (Test-Path "C:\Work\FilesThatNeedToBeChanged.txt") { # if file exists
Remove-Item "C:\Work\FilesThatNeedToBeChanged.txt"
}
(Get-Content "C:\Work\NumberXrefList.CSV" |where {$_.readcount -gt 1}) | foreach{
$OldFieldValue, $NewFieldValue = $_.Split("|")
$filenamelist = (Get-Content "C:\Work\ListofAllFilenamesToSearch.txt" -ReadCount 5) #|
foreach ($j in $filenamelist) {
#$testvar = (Get-Content $j )
#$testvar = (Get-Content $j -ReadCount 100)
$testvar = (Get-Content $j -Delimiter "\n")
Foreach ($i in $testvar)
{
if ($i -imatch $OldFieldValue) {
$j + "|" + $OldFieldValue + "|" + $NewFieldValue | Out-File "C:\Work\FilesThatNeedToBeChanged.txt" -Width 2000 -Append
}
}
}
}
$FileFolder = (Get-Content "C:\Work\FilesThatNeedToBeChanged.txt" -ReadCount 5)
Get-ChildItem $FileFolder -Recurse |
select -ExpandProperty fullname |
foreach {
if (Select-String -Path $_ -SimpleMatch $OldFieldValue -Debug -Quiet) {
(Get-Content $_) |
ForEach-Object {$_ -replace $OldFieldValue, $NewFieldValue }|
Set-Content $_ -WhatIf
}
}
In the code above, I've tried several things with Get-Content - default, with -ReadCount, and -Delimiter - in an attempt to avoid an out of memory error.
The only thing I have control over is the length of the old & new replacement strings file. Is there a way to do this in Powershell? Is there a better option/solution? I'm running Windows 7, Powershell version 3.0.
Your main problem is that you're reading the file over and over again to change each of the terms. You need to invert the looping of the replace terms and looping of the files. Also, pre-load the csv. Something like:
$filefolder1 = "C:\TestFolder\WorkFiles"
$ftype = "*.txt"
$filenames = gci -Path $filefolder1 -Filter $ftype -Recurse
$replaceValues = Import-Csv -Path "C:\Work\NumberXrefList.CSV"
foreach ($file in $filenames) {
$contents = Get-Content -Path $file
foreach ($replaceValue in $replaceValues) {
$contents = $contents -replace $replaceValue.OldValue, $replaceValue.NewValue
}
Copy-Item $file "$file.old"
Set-Content -Path $file -Value $contents
}

Powershell. Need help importing hostnames from .csv. The rest of this works

I am trying to figure out how to correct this script I've wrote. I know it is something wrong with the way it is importing the list of hostnames. I don't know how to fix it.
Part 1: This is supposed to import a .csv with the hostnames and dig the registry for the application's uninstall information, put it into an array, and export into .csv's for later use. Also it creates .txt files in order to later compare the applications on the system to a baseline.
$path = "\\path"
$computers = Import-Csv -Path "\\Path\hostnames.csv"
$array = #()
foreach($pc in $computers)
{
$computername = $pc.computername
#$computername = "KNOWN_HOSTNAME" #test line for one system
$UninstallKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
$reg = [microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$computername)
$regkey = $reg.OpenSubKey($UninstallKey)
$subkeys = $regkey.GetSubKeyNames()
foreach($key in $subkeys)
{
$thisKey=$UninstallKey+"\\"+$key
$thisSubKey=$reg.OpenSubKey($thisKey)
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $computername
$obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $($thisSubKey.GetValue("DisplayName"))
$obj | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $($thisSubKey.GetValue("DisplayVersion"))
$obj | Add-Member -MemberType NoteProperty -Name "Publisher" -Value $($thisSubKey.GetValue("Publisher"))
$obj | Add-Member -MemberType NoteProperty -Name "InstallDate" -Value $($thisSubKey.GetValue("InstallDate"))
$array += $obj
$ExportArray = $array | Where-Object { $_.DisplayName } |
select ComputerName , DisplayName, DisplayVersion, Publisher, InstallDate
$ExportArray |
Export-csv $path\$computername.csv -NoTypeInformation
$ExportArray2 = $array |
Where-Object { $_.DisplayName } |
select DisplayName, DisplayVersion, Publisher
$ExportArray2 |
Export-csv $path\$computername.txt -NoTypeInformation
}
}
Part 2: This portion compiles the .csv's into one excel document for reporting
$csvs = Get-ChildItem $path\* -Include *.csv
$outputfilename = "Network_" + (Get-Date -Format yyyyMMdd)
$excelapp = new-object -comobject Excel.Application
$excelapp.sheetsInNewWorkbook = $csvs.Count
$xlsx = $excelapp.Workbooks.Add()
$sheet=1
foreach ($csv in $csvs)
{
$row=1
$column=1
$worksheet = $xlsx.Worksheets.Item($sheet)
$worksheet.Name = $csv.Name
$file = (Get-Content $csv.PSPath | ForEach-Object {$_ -replace '"', ""})
foreach($line in $file)
{
$linecontents = $line -split ‘,(?!\s*\w+”)’
foreach($cell in $linecontents)
{
$worksheet.Cells.Item($row,$column) = $cell
$column++
}
$column = 1
$row++
}
$sheet++
}
$output = $path + “\” + $outputfilename + ".xlsx"
$xlsx.SaveAs($output)
$excelapp.quit()
Part 3: This portion loads up a baseline, and the .txt's created preciously, and checks for differences in the files. (also deletes blank ouput files)
$bline = Get-ChildItem $path\* -Include Baseline.txt
$txts = Get-ChildItem $path\* -Include *.txt -Exclude Baseline.txt
foreach ($txt in $txts)
{
Compare-Object -referenceobject $(Get-Content $bline) -differenceobject $(Get-Content $txt) |
ft inputobject, #{n = "file"; e = {if ($_.SideIndicator -eq '=>') {"System"} else {"Baseline"}}} |
Out-File $txt'_has_diff'.csv -Width 256
Get-ChildItem $path |
where {$_.Length -eq 0} |
Remove-Item
}
Thank you
Edit:
The Hostnames.csv files I've tried are:
HOSTNAME1
HOSTNAME2
and
"HOSTNAME1","HOSTNAME2"
It's a little unclear what the problem is, because you say there is "something wrong with the way it is importing the list of hostnames", but you haven't specified what kind of results you're getting and how they differ from the intended results.
However, based on your sample data I think I can infer what the problem is: You're trying to use Import-Csv on non-CSV data. Neither of your examples looks like a CSV file. They both look like lists. A list in which the items are separated by commas, such as
"HOSTNAME1","HOSTNAME2","HOSTNAME3","HOSTNAME4"
is not called a "CSV file". CSV files are a form of "flat file", in which the data represents the rows and columns of a single database table. An example of a CSV file would be something like this, where the first line is a list of field (column) names, and the other lines are records (rows) with the comma-separated values corresponding to the columns in the header row:
"Hostname","OS","OS Version","Primary Function","Location"
"BOSEXCH01","Windows","Server 2012","Microsoft Exchange","Boston"
"BOSDC01","Windows","Server 2008 R2","Active Directory domain controller","Boston"
"MYWEB","Linux","Ubuntu 13.04","Apache web server","Phoenix"
The cmdlet Import-Csv imports a CSV file into an array of objects in which the properties are the field names in the header row, and the values are the comma-separated items in each row corresponding to the property names derived from the header row. Export-Csv does the reverse—it creates a CSV file from an array of objects.
It looks like what you're trying to do is read a simple list of hostnames into an array of strings. If your data looks like the first example,
HOSTNAME1
HOSTNAME2
[etc...]
you can read it into an array by simply using Get-Content, as follows (note that I changed the extension to .txt to reflect the actual format of the data):
$computers = Get-Content "\\Path\hostnames.txt"
If your data looks like the second example,
"HOSTNAME1","HOSTNAME2",[etc...]
you can read it into array like this:
$computers = (Get-Content "\\Path\hostnames.txt") -split ','
On the other hand, it appears that you are using Export-Csv correctly: You're exporting a bunch of objects with the same properties into a flat file, which is the correct usage of the term "CSV".