when I try to export to a CSV list, I only get all number for "Length"
.Count property until the split point is reached, then split the CSV array to a new file with a new name that will be used from this point on. What might be the issue?
$RootFolder = Get-Content "c:\DRIVERS\myfile.txt"
foreach ($arrayOfPaths in $RootFolder){
$csv = $arrayofPaths -replace '^\\\\[^\\]+\\([^\\]+)\\([^\\]+).*', 'C:\output\Company_name_${1}_${2}.csv'
$csvIndex = 1
$maxRows = 1000000
$rowsLeft = $maxRows
Get-ChildItem $arrayOfPaths -Recurse | Where-Object {$_.mode -match "d"} | ForEach-Object {
#$csv = $_.FullName -replace '^\\\\[^\\]+\\([^\\]+)\\([^\\]+).*', 'C:\output\Company_name_${1}_${2}.csv'# <- construct CSV path here
$path = $_.FullName
$thisCSV = Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
ConvertTo-Csv
if ($thisCSV.count -lt $rowsLeft) {
$thisCSV | Export-Csv $csv -append -noType
$rowsLeft -= $thisCSV.count
} else {
$thisCSV[0..($rowsLeft - 1)] | Export-Csv $csv -append -noType
$csvIndex++
$csv = $csv -replace '\.csv$', "$csvIndex.csv"
if ($thisCSV.count -gt $rowsLeft) {
$thisCSV[$rowsLeft..($thisCSV.count - 1)] | Export-Csv $csv -append -noType
}
$rowsLeft = $maxRows - ($thisCSV.count - $rowsLeft)
}
}
}
Export-CSV is built to take PSCustomObjects as input, not lines of text.
$thisCSV = Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
ConvertTo-Csv
The output of this line will be something like:
#TYPE Selected.System.Security.AccessControl.FileSystemAccessRule
"Path","IdentityReference","AccessControlType","FileSystemRights"
"c:\test","BUILTIN\Administrators","Allow","FullControl"
At least three lines, an array of string. What properties does an array of string have?
PS C:\> 'a','b' | Get-Member -MemberType Property
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Length Property int Length {get;}
Length. The only property you see in the CSV, because Export-CSV is exporting all the properties, and that's the only property.
Fix: Remove | ConvertTo-CSV from the Get-ACL line, leave your custom objects as custom objects and let the export handle converting them.
(This should also fix the counting, because it's not counting 3+ lines of text while trying to export 1+ line of data every time).
Related
Being a beginner in Powershell, I have a problem that I can't solve. I get the average of different CSV files as a string with the following code:
# recovery of the list of csv files present in the folder "folder_1".
$files=(Get-ChildItem -path "C:\folder_1\" -Recurse -Include *.csv)
#loop to read each file and average the variables "PRESS_CELL" and "PRESS_DELTA
foreach($file in $files){
$varTemp = #((Get-Content $file | ConvertFrom-Csv | Measure-Object "PRESS_CELL","PRESS_DELTA" -Average | Export-Csv -Path "C:\folder_1\Alias.csv" -NoTypeInformation -Append))
Write-Host $varTemp
}
#added an increment to sort the data (averages)
$vartemp2 = Import-CSV "C:\folder_1\Alias.csv" | Select *,LINENUMBER | ForEach-Object -Begin { $Line = 1 } {
$_.LineNumber = $Line++
$_
} | Export-CSV "C:\folder_1\Alias2.csv" -NoTypeInformation
Write-Host $vartemp2
# sort data by "property" and by "LINENUMBER"
$vartemp3 = Import-Csv "C:\folder_1\Alias2.csv"
$vartemp3 | % { $_.LINENUMBER = [int]$_.LINENUMBER }
$vartemp3 | Sort-Object -Property #{ Expression = 'Property'; Ascending = $true }, #{ Expression = 'LINENUMBER'; Ascending = $true } |
Format-Table -Property "Average","Property","LINENUMBER"
# groups the values obtained in a table/customobject and export it to csv by column ?
$fields = [ordered]#{
PRESS_CELL = $vartemp3 | ? property -like *PRESS_CELL* | Select -ExpandProperty Average
PRESS_DELTA = $vartemp3 | ? property -like *PRESS_DELTA* |Select -ExpandProperty Average
}
$fields | export-csv C:\1_ICOS_data\Alias4.csv -Append ##DOESN'T WORK
[result][1]
However, I would like to export the result as a CSV table (1 column per result with PRESS_CELL and PRESS_DELTA as headers. When I use the pipeline :
| export-csv C:\temp\alias.csv -Append
I get a result :
With "ordered"
"System.Collections.Specialized.OrderedDictionary+OrderedDictionaryKeyValueCollection","System.Collections.Specialized.OrderedDictionary+OrderedDictionaryKeyValueCollection","False","System.Object","False"
And with pscustomobject :
System.Object[],"System.Object[]"
Add -NoTypeInformation to export-csv command like that
$fields = [ordered]#{
PRESS_CELL = $vartemp3 | ? property -like *PRESS_CELL* | Select -ExpandProperty Average
PRESS_DELTA = $vartemp3 | ? property -like *PRESS_DELTA* |Select -ExpandProperty Average
}
#Or:
$fields = [pscustomobject]#{
PRESS_CELL = $vartemp3 | ? property -like *PRESS_CELL* | Select -ExpandProperty Average
PRESS_DELTA = $vartemp3 | ? property -like *PRESS_DELTA* |Select -ExpandProperty Average }
$fields |export-csv "c:\fields.csv" -Append -NoTypeInformation
I am looking to recursively grab a list of recently modified files under two network drives, sort them in descending date order, and make some edits to the CSV file to tidy the list for Excel
I have cobbled the code below from a number of sources (I am a powershell beginner) and it is now doing what I need (i.e. producing a list).
I need help in going a step further, I cannot sort the resultant CSV file by file last write time date, is this because my array is expecting text rather than a numeric field?
I also am returning the domain name as well as the file owner with ((Get-ACL $_.FullName).Owner). I tried using Replace to cut down the string, but had no luck with this approach.
$arr = #()
$days_to_check=$(Get-Date).AddDays(-28)
$items = #(Get-ChildItem '\\ND\dir 1\*.*' -Recurse -ErrorAction SilentlyContinue | where { $_.LastWriteTime -gt $days_to_check})
$items += #(Get-ChildItem '\\ND\dir 1\*.*' -Recurse -ErrorAction SilentlyContinue |
where { $_.LastWriteTime -gt $days_to_check})
$items | Foreach {
$obj = New-Object PSObject -prop $hash
$obj | Add-Member NoteProperty FullName $_.FullName
$obj | Add-Member NoteProperty Directory $_.Directory
$obj | Add-Member NoteProperty Name $_.Name
$obj | Add-Member NoteProperty LastTime $_.LastWriteTime
$obj | Add-Member NoteProperty Owner ((Get-ACL $_.FullName).Owner)
$arr += $obj
}
$arr | Format-List
$arr | Sort-Object -Property LastTime -Descending
$arr | Export-CSV -notypeinformation C:\temp\filenamesFO.csv
CSV file sorted by date field
You did sort your array in the output but that's all you did.
If you want to actually export it that way, you have to assign the sort to $arr
Replace
$arr | Sort-Object -Property LastTime -Descending
with
$arr = $arr | Sort-Object -Property LastTime -Descending
You can remove the Owner domain using the following Replace -replace '(.*\\)(.*)','$2'
Here's a complete example implementing the changes mentionned above.
$arr = new-object -TypeName 'System.Collections.Generic.List[PSObject]'
$days_to_check=$(Get-Date).AddDays(-28)
$items = #(Get-ChildItem '\\ND\dir 1\*.*' -Recurse -ErrorAction SilentlyContinue | where { $_.LastWriteTime -gt $days_to_check})
$items += #(Get-ChildItem '\\ND\dir 1\*.*' -Recurse -ErrorAction SilentlyContinue |
where { $_.LastWriteTime -gt $days_to_check})
Foreach ($item in $items) {
$obj = [PSCustomObject]#{
FullName = $item.FullName
Directory = $item.Directory
Name = $item.Name
LastTime = $item.LastWriteTime
Owner = (Get-ACL $item.FullName).Owner -replace '(.*\\)(.*)','$2'
}
$arr.add($obj)
}
$arr = $arr | Sort-Object -Property LastTime -Descending
#$arr | Format-List
$arr | Export-CSV -notypeinformation C:\temp\filenamesFO.csv
I made some additional changes:
Instead of using an array, I used a List of PSObject. If you have a lot of files, the processing time will be improved in comparison with an array.
I used the PSCustomObject declaration just to show an alternative to all those Add-member. I find it cleaner but it is up to you in the end.
I would like to get the difference in the columns in as a table but I only can do a comparison with two columns and it doesn't display all the columns. I need to see in which column the cell is not present in the first column.
The file:
ComputerName OtherComputerName OtherComputer AndAgain
infra-1 infra-852 infra-2 infra-99
infra-98 infra-85 infra-44 infra-23
infra-5 infra-8 infra-1 infra-1
infra-2 infra-55 infra-8 infra-70
infra-62 infra-5 infra-852 infra-5
The current result:
ComputerName OtherComputerName OtherComputer AndAgain
------------ ----------------- ------------- --------
I would like to get this as result in PowerShell:
ComputerName OtherComputerName OtherComputer AndAgain
------------ ----------------- ------------- --------
infra-1 infra-852 infra-99
infra-98 infra-85 infra-44 infra-23
infra-5 infra-8
infra-2 infra-55 infra-8 infra-70
infra-62 infra-852
Edit
I have some errors too when I run this code.
The script:
$csv = Import-Csv .\test1.csv -Delimiter ';'
$ref = #($csv.ComputerName)
foreach ($row in $csv) {
foreach ($col in 'OtherComputerName', 'OtherComputer', 'AndAgain') {
if ($ref -contains $row.$col) { $row.$col = '' }
}
}
$table = #()
$file = Get-Content .\test1.csv
$file = $file -replace(" "," ")
$file = $file -replace(" "," ")
$file = $file -replace(" "," ")
$file = $file -replace(" - "," ")
[string[]]$a = Import-Csv '.\test1.csv' | select -Expand ComputerName
[string[]]$b = Import-Csv '.\test1.csv' | select -Expand OtherComputerName
[string[]]$c = Import-Csv '.\test1.csv' | select -Expand OtherComputer
[string[]]$d = Import-Csv '.\test1.csv' | select -Expand AndAgain
$b | ? {$a -notcontains $_}
$c | ? {$a -notcontains $_}
$d | ? {$a -notcontains $_}
foreach ($line in $file) {
$lineb = $line -split(" ")
$obj = New-Object PSObject
$obj | Add-Member -Name "ComputerName" -MemberType NoteProperty -Value $lineb[1]
$obj | Add-Member -Name "OtherComputerName" -MemberType NoteProperty -Value $lineb[1]
$obj | Add-Member -Name "OtherComputer" -MemberType NoteProperty -Value $lineb[2]
$obj | Add-Member -Name "AndAgain" -MemberType NoteProperty -Value $lineb[3]
$table += $obj
}
$table | ft -AutoSize
You need to read the values of the first column into an array, compare the values of the other columns against that array, and clear matching fields:
$csv = Import-Csv .\test1.csv -Delimiter ';'
$ref = #($csv | Select-Object -Expand ComputerName)
foreach ($row in $csv) {
foreach ($col in 'OtherComputerName', 'OtherComputer', 'AndAgain') {
if ($ref -contains $row.$col) { $row.$col = '' }
}
}
I use Export-Excel module for Powershell. I try to get results of "foreach" from 2 links in a table. But finally i have only one link in the table(only second one). "Out-File" has "=Append",that appends to a file. Maybe there is something like this for "Export-Excel"?
[Reflection.Assembly]::LoadFrom("C:\selenium\net40\WebDriver.dll")
$url = Get-Content D:\dww.txt
$ie = New-Object OpenQA.Selenium.PhantomJS.PhantomJSDriver
foreach ($u in $url) {
$ie.Navigate().GoToUrl($u)
$title = $ie.FindElementByXPath("//h1[contains(#class, 'fullstory')]")
$fullstory = $ie.FindElementByClassName("comment")
$tracklist = $ie.FindElementByXPath("//*[contains(#id,'news-id')]")
$links = $ie.FindElementByXPath("//*[contains(#class, 'link')]")
$img = $ie.FindElementsByclassname("stars").findelementbytagname("img").getattribute("src")
$h = Write-Output Стиль,Формат,"Год выпуска",Размер,"Название альбома",Исполнитель,Треклист,Ссылка,Обложка
$data = ($fullstory.text).split("`n") -replace ": ","=" | Where {$_.Trim()} | Out-String | ConvertFrom-StringData | Foreach {[pscustomobject]$_} | Select $h
$data.Ссылка = $links.text
$data.Треклист = $tracklist.text
$data.Обложка = $img
$data | Export-Excel d:\filedark2.xlsx -AutoSize
Write-Host $u " - выгружено"
}
$ie.Quit()
if you're only using export-excel to save to a new excel document, you might try just exporting to csv using -append and converting to excel afterward with this
https://github.com/gangstanthony/PowerShell/blob/master/Save-CSVasExcel.ps1
...
$data | Export-Csv d:\filedark2.csv -Append -NoTypeInformation
...
}
Save-CSVasExcel d:\filedark2.csv
...
I am trying to get it easier to use on file servers. I would like to import a file called shares.txt. In that shares.txt there are for example lines, e.g. folder name → root folder and share name → subfolder.
\\10.10.15.240\folder name\share name
\\10.10.15.240\folder name\share2 name
\\10.10.15.240\folder name\share3 name
\\10.10.15.240\folder2 name\share name
\\10.10.15.240\folder2 name\share2 name
\\10.10.15.240\folder2 name\share3 name
and so on.
And I would like to create the output to:
Outputs the data to a text file on \\10.10.15.240\output\ using the folder name and share name as part of the file name
\\10.10.15.240\output\Company_name_$folder name_$share name.csv
\\10.10.15.240\output\Company_name_$folder name_$share2 name.csv
\\10.10.15.240\output\Company_name_$folder name_$share3 name.csv
\\10.10.15.240\output\Company_name_$folder2 name_$share name.csv
\\10.10.15.240\output\Company_name_$folder2 name_$share2 name.csv
\\10.10.15.240\output\Company_name_$folder2 name_$share3 name.csv
and continue.
Do you know how to import this in your script? I tried several things but they all comes up with errors.
Script:
I want to write the permissions list to a CSV file instead of writing it directly to Excel.
$ErrorActionPreference = "SilentlyContinue"
$a = New-Object -ComObject Excel.Application
$a.visible = $true
$b = $a.Workbooks.Add()
$intRow = 1
$c = $b.Worksheets.Item(1)
$c.Cells.Item($intRow,1) = "Folder"
$c.Cells.Item($intRow,2) = "Compte/groupe"
$c.Cells.Item($intRow,3) = "Type d'Acces"
$c.Cells.Item($intRow,4) = "Droits"
$d = $c.UsedRange
$d.EntireColumn.AutoFit()|Out-Null
$d.Interior.ColorIndex = 19
$d.Font.ColorIndex = 11
$d.Font.Bold = $true
Remove-Variable arrayOfPath
$depth = 2
$RootFolder = "\\MySRV\Folder"
for ($i=0; $i -le $depth; $i++) {
$arrayOfPath += ,$RootFolder
$RootFolder = $RootFolder + "\*"
}
$arrayOfPath | Get-ChildItem | %{
Get-Acl $_.FullName
} | %{
$intRow = $intRow + 1
$c.Cells.Item($intRow, 1) = $_.Path.ToString().Replace("Microsoft.PowerShell.Core\FileSystem::", "")
$droit = $_.Access
$droit | %{
$c.Cells.Item($intRow, 2) = $_.IdentityReference.ToString();
$c.Cells.Item($intRow, 3) = $_.AccessControlType.ToString();
$c.Cells.Item($intRow, 4) = $_.FileSystemRights.ToString();
$intRow = $intRow+1
}
}
$d.EntireColumn.AutoFit() | Out-Null
Last Update:
$arrayOfPaths= Get-Content "\\UNC PATH\myfile.txt"
Get-ChildItem $arrayOfPaths -Recurse | Where-Object {$_.mode -match "d"} | ForEach-Object {
$csv = $_.FullName -replace '^\\\\[^\\]+\\([^\\]+)\\(.*)', '\\UNC PATH\Company_name_${1}_${2}.csv' # <- construct CSV path here
$path = $_.FullName
Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
Export-Csv $csv -Append -NoType
}
Basically you'd do something like this:
loop over the paths
get each folder's ACL
expand the ACEs
select the ACE properties you want exported
add the path with a calculated property
export the selected properties to a CSV
Appending to the output CSV(s) inside the loop allows you to control to which file each ACL is exported. You can for instance make the file name depend on elements of the source path, or the number of elements already written (if you add a counter variable).
Get-ChildItem $arrayOfPaths | ForEach-Object {
$csv = "..." # <- construct CSV path here
$path = $_.FullName
Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
Export-Csv $csv -Append -NoType
}
}
Note that -Append was added to Export-Csv in PowerShell v3. On earlier versions you can sort of emulate it with ConvertTo-Csv and Add-Content.