How to read NTFS permissions in a list of shares from a text file - excel

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.

Related

Clipboard access denied, csv to xlsx conversion

I have a most peculiar issue with clipboard. Below is the code I've written that in essence gathers info about many many thousands of files, compares hashes, compares filnames and lists zero length files and then writes them all to an xlsx file in separate worksheets.
Everything works fine if the scope is relatively small (i.e. ~20k files), but if the scope becomes greater (i.e. ~200k files) I get an error Clipboard access denied. Initially I believed that the issue was clipboard capacity, as I use clipboard and .pastespecial method. But when intermediate csv files are created and their contents copied, everything seems to work fine. Ant thoughts?
Original script
$excel = New-Object -com excel.application
$excel.SheetsInNewWorkbook = 2
$excel.displayalerts = $false
$workbook = $excel.workbooks.add()
$worksheet = $workbook.worksheets
$True_Dups = $worksheet.item(1)
$True_Dups.name = "True Duplicates"
$Dupes = $worksheet.item(2)
$Dupes.name = "Name Duplicates"
$wbPersonalXLSB = $excel.workbooks.open("$env:USERPROFILE\Application Data\Microsoft\Excel\XLSTART\PERSONAL_2.XLSB")
$path = "PATH"
$GCI = GCI $path -file -Recurse -Ea 0
$hashes =
$GCI|
Get-FileHash -Algorithm MD5 -Ea 0|
select Algorithm, Hash, #{l="File";e={$_.Path.split("\")|select -Last 1}},#{l="Path";e={$_.Path.Substring(0,$_.Path.LastIndexof('\'))}}, #{l="Link";e={$_.Path}}|
Group -property "Hash"|
Where {$_.Count -ge 2}|
select -Expand Group
$hashes|ConvertTo-Csv -NoTypeInformation -Delimiter "`t"|scb
$True_Dups.Cells.Item(1).pastespecial()|out-null
$True_Dups.activate()
$excel.run("PERSONAL_2.XLSB!Empty_Row_Dupes")
$filenames =
$GCI|
Select #{l='File';e={$_.PSChildName}}, #{l='Compare Filename';e={$_.BaseName.replace('_','*').replace(' ','*').replace('-','*')}}, Directory, FullName, #{l="Extension";e={$_.Extension}}|
group -Property 'Compare Filename'|
Where {#($_.Group.Extension |Sort -Unique).Count -ge 2}|
select -expand Group
$filenames|ConvertTo-Csv -NoTypeInformation -Delimiter "`t"|scb
$Dupes.Cells.Item(1).pastespecial()|out-null
$Dupes.Activate()
$excel.run("PERSONAL_2.XLSB!Empty_Row_Dupes")
$wbPersonalXLSB.Close()
$Empty = $worksheet.add([System.Reflection.Missing]::Value,$worksheet.Item($worksheet.count))
$Empty.Name = "Zero Lenght"
$zero_length =
$GCI|
? {$_.Length -eq 0}|
Select #{l='File';e={$_.PSChildName}}, Length, Directory, FullName
$zero_length|ConvertTo-Csv -NoTypeInformation -Delimiter "`t"|scb
$zero_length.cells.item(1).pastespecial()|out-null
$zero_length.range("A1:D1").Interior.Color = 8454080
$save = "CSV_PATH"
$workbook.saveas($save)
$workbook.close()
$excel.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)|out-null
Remove-Variable excel
Interdemiate CSVs added
$start = Get-Date
$path = "Path"
$GCI = GCI $path -file -Recurse -Ea 0
$hashes =
$GCI|
Get-FileHash -Algorithm MD5 -Ea 0|
select Algorithm, Hash, #{l="File";e={$_.Path.split("\")|select -Last 1}},#{l="Path";e={$_.Path.Substring(0,$_.Path.LastIndexof('\'))}}, #{l="Link";e={$_.Path}}|
Group -property "Hash"|
Where {$_.Count -ge 2}|
select -Expand Group
$hashes|export-Csv "PATH_1 csv" -NoTypeInformation
$filenames =
$GCI|
Select #{l='File';e={$_.PSChildName}}, #{l='Compare Filename';e={$_.BaseName.replace('_','*').replace(' ','*').replace('-','*')}}, Directory, FullName, #{l="Extension";e={$_.Extension}}|
group -Property 'Compare Filename'|
Where {#($_.Group.Extension |Sort -Unique).Count -ge 2}|
select -expand Group
$filenames|export-Csv "PATH_2.csv" -NoTypeInformation
$zero_length =
$GCI|
? {$_.Length -eq 0}|
Select #{l='File';e={$_.PSChildName}}, Length, Directory, FullName
$zero_length|export-Csv "PATH_3.csv" -NoTypeInformation
$span = ((get-date) - $start).ToString("hh\:mm\:ss")
Write "Span lasted $span"
and conversion script (credit goes to the original creator linked at the end)
$path = "CSV_FOLDER"
$csvs = Get-ChildItem $path -filter *.csv
$y = $csvs.Count
Write-Host "Detected the following CSV files: ($y)"
Write-Host " "$csvs.Name"`n"
$outputfilename = "Final Registry Results"
Write-Host Creating: $outputfilename
$excelapp = New-Object -ComObject Excel.Application
$excelapp.SheetsInNewWorkbook = $csvs.Count
$xlsx = $excelapp.Workbooks.Add()
for($i=1;$i -le $y;$i++) {
$worksheet = $xlsx.Worksheets.Item($i)
$worksheet.Name = $csvs[$i-1].Name
$file = (Import-Csv $csvs[$i-1].FullName)
$file | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Clip
$worksheet.Cells.Item(1).PasteSpecial()|out-null
}
$output = "XLSX_OUTPUT"
$xlsx.SaveAs($output)
$excelapp.Quit()
Merging CSV Files into a XLSX with Tabs

Powershell get infos about files and try to Export them

I try do write a script where i can choose a folder and powershell shows me the Name, Size,.... of all the files in that folder. After that powershell should export the Informations in a Excel Table.
But im stuck and dont know what to do :C
Here is my code that i tried to build
Function Get-Folder($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")|Out-Null
$foldername = New-Object System.Windows.Forms.FolderBrowserDialog
$foldername.Description = "Select a folder"
$foldername.rootfolder = "MyComputer"
if($foldername.ShowDialog() -eq "OK")
{
$folder += $foldername.SelectedPath
}
return $folder
}
$a = Get-Folder
$folder = $a
Get-ChildItem -Path $folder | SELECT Name, #{Name="Size In KB";Expression={$_.Length / 1Kb}}, Attributes, LastaccessTime, #{n='Owner';e={(get-acl $_.Fullname).Owner}}| Format-Table -AutoSize
Export-Csv "C:\Users\DZimmermann\Desktop\Test.csv" -Delimiter ";" -Append
As commented, using Format-Table -AutoSize simply outputs the info in a table format to console. It returns nothing, so there is nothing to write in the csv file..
Doing like this will create the CSV file and writes the info in there:
Get-ChildItem -Path $folder |
Select-Object Name,
#{Name="Size In KB";Expression={$_.Length / 1Kb}},
Attributes, LastaccessTime,
#{n='Owner';e={(get-acl $_.Fullname).Owner}} |
Export-Csv "C:\Users\DZimmermann\Desktop\Test.csv" -Delimiter ";"
This will not get you the info on screen. If you also want that, capture the result in a variable first:
$result = Get-ChildItem -Path $folder |
Select-Object Name,
#{Name="Size In KB";Expression={$_.Length / 1Kb}},
Attributes, LastaccessTime,
#{n='Owner';e={(get-acl $_.Fullname).Owner}}
#output on screen
$result | Format-Table -AutoSize
# write the CSV file:
$result | Export-Csv "C:\Users\DZimmermann\Desktop\Test.csv" -Delimiter ";"
P.S. judging by the title of this question, I think you only want info about Files, not Directories..
If that is the case, add -File switch to the Get-ChildItem cmdlet (for PS 3 and up). For PS versions below 3 use
Get-ChildItem -Path $folder | Where-Object { !$_.PSIsContainer }

Export-CSV only gets the "Length"

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).

add colum to merged csv file

Ok heres what I have code wise:
$a = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\*.csv"
$b = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\merge.csv"
(get-content $a) | set-content $b
This pulls all the data of all the files into one merged file, but I need one additional item, I need to pull the name of the individual files and append it to the first column of the file for multiple files, several hundred at a time.
Not tested but something like this should do it:
$a = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\*.csv"
$b = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\merge.csv"
Get-ChildItem $a | % {
Import-Csv $_.Fullname | Add-Member -MemberType NoteProperty -Name 'File Name' -Value $_.Name
} | Export-Csv $b
Assuming the CSV files each have the same column headings, I would lean toward using Import-CSV instead of Get-Content so that you can work with the CSV contents as arrays of objects with named properties.
Then all you need to do is iterate through each item of the array and append a property containing the file path, which you can do using the Add-Member cmdlet. Once that's done, export the array of objects using the Export-CSV cmdlet.
$directory = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\"
$search = $directory + "*.csv"
$exportpath = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\merge.csv"
$paths = get-childitem $search
$objectArrays = #()
$paths | %{
$filepath = $_.fullname;
$objectArray = Import-CSV $filepath;
$objectArray | %{
Add-Member -inputobject $_ -Name "SourceFile" -Value $filepath -MemberType NoteProperty};
$objectArrays += $objectArray}
$objectArrays | export-csv -path $exportpath -notype
This puts the SourceFile property as the last column in the outputted CSV file
Ok, simplification... Search target folder, pipe to a ForEach-Object loop (shorthand % used), capture the file name as variable, import the CSV, add the sourcefile using the Select-Object cmdlet, convert it back to a CSV, end loop, pipe to destination file.
$a = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\*.csv"
$b = "C:\Users\some.deranged.character\Desktop\SomeAwfulPlace\Checklists\C_F\merge.csv"
GCI $a | %{$FileName=$_.Name;Import-CSV $_|Select #{l='SourceFile';e={$FileName}},*|ConvertTo-CSV -NoType} | set-content $b

Powershell filter a List by Name and Date

I need a bit of help... I'm new to powershell and i want to Filter a List (csv). I would love to remove all lines with certain names in it. and cut the list down to the last month. In the script you can see how far i got till now.
param(
[Parameter(ValueFromPipeline=$true,HelpMessage="Enter CSV path(s)")]
[String[]]$Path = $null
)
if($Path -eq $null) {
Add-Type -AssemblyName System.Windows.Forms
$Dialog = New-Object System.Windows.Forms.OpenFileDialog
$Dialog.InitialDirectory = "$InitialDirectory"
$Dialog.Title = "Select CSV File(s)"
$Dialog.Filter = "CSV File(s)|*.csv"
$Dialog.Multiselect=$true
$Result = $Dialog.ShowDialog()
if($Result -eq 'OK') {
Try {
$Path = $Dialog.FileNames
}
Catch {
$Path = $null
Break
}
}
else {
Write-Host -ForegroundColor Yellow "Notice: No file(s) selected."
Break
}
}
$info=Import-Csv "$path" -Delimiter ';'
$info | Get-Member
$info | Format-Table
as you can see i tryed to link the path to a filebrowser.
For the purposes of discussion, I will assume that the full pathname of the CSV is in the variable $InputPath, and that you want to write the result to a CSV file whose full pathname is in the variable $OutputPath. I will also assume that the CSV file contains a column named 'Name', and that the value from the Name column that you want to exclude is in the variable $ExcludedName. Given that, you can simply do
Import-CSV -Path $InputPath | Where-Object {$_.Name -ne $ExcludedName} | Export-CSV -Path $OutputPath -NoTypeInformation
You can do this by my code,but dont forget that first row must contains names of column and delimiter must be ';' and $nameslist is array of names that you need delete:
$info=Import-Csv "D:\testdir\file2.csv" -Delimiter ';'
$nameslist=#('James','John','andrew')
foreach($i in $info){
if($nameslist -contains $i.Name){
$i.Name=""
}
$i|Export-Csv -Path "D:\testdir\file1.csv" -Delimiter ';' -NoTypeInformation -Force -Encoding UTF8 -Append
}
Try this:
$data = Import-Csv "Path" | Select-Object * -ExcludeProperty Names
$data | export-csv "Path" -Notype
This will cut the column names.
Try it first without using a function:
Import-Csv <Filename> | Where-Object {$_.<FieldName> -notlike "*<Value>*"}
Also, you might consider something like this:
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true, HelpMessage = "Enter CSV path(s)")]
[String[]]$Path = $(
Add-Type -AssemblyName System.Windows.Forms
$DialogProperties = #{
Title = 'Select CSV File(s)'
Filter = 'CSV File(s)|*.csv'
Multiselect = $True
}
$Dialog = New-Object System.Windows.Forms.OpenFileDialog -Property $DialogProperties
$Dialog.ShowDialog()
If ($Result -eq 'OK') {
$Path = $Dialog.FileNames
} Else {
Write-Error 'Notice: No file(s) selected.'
}
)
)
Process {
ForEach ($PathItem in $Path) {
Import-Csv $PathItem | Where-Object { $_.Name -notlike "*NotThisOne*" }
}
}

Resources