I'm trying to do an audit of some folders. I need to get NTFS permissions of every folder listed in input file. I have a folderlist.txt with folder paths.
This is the script I have:
$InputFile = "C:\Folderlist.txt"
$OutputFile = "C:\FolderPermissions.csv"
$FolderList = Get-Content $InputFile
ForEach ($Folder in $FolderList)
{
$Permissions = (Get-ACL $Folder).access | ForEach-Object {$_ |
Add-Member -MemberType NoteProperty -Name Folder -Value $Folder}
$Report += $Permissions
}
$Report | Select-Object Folder,IdentityReference,FileSystemRights,IsInherited |
Where {$_.Folder -ne $Null -and $_.IdentityReference -like "HARRAHS*" -and $_.IsInherited -ne "TRUE"} |
Export-CSV $OutputFile -NoTypeInformation
but it does not give any output. I'm powershell noob, can someone please guide me and tell me what am I doing wrong?
The output I need is basically name of the folder and groups and users with permissions. E.g.:
Folder Path IdentityReference AccessControlType
C:\Folder1\ DOMAIN\User1 Read
C:\Folder1\ DOMAIN\Group1 Write
C:\Folder2\ DOMAIN\User2 Modify
C:\Folder2\ DOMAIN\Group2 Full
Any help is greatly appreciated. Thanks a lot.
This is your culprit:
$Permissions = (Get-ACL $Folder).access | ForEach-Object {
$_ | Add-Member -MemberType NoteProperty -Name Folder -Value $Folder
}
You pipe the ACEs into a loop where you add a property to each. However, the | Add-Member construct doesn't output the modified objects, so there's nothing left to be assigned to $Permissions.
This could be fixed by adding ; $_ after the Add-Member statement in order to re-inject the objects into the pipeline:
$Permissions = (Get-ACL $Folder).access | ForEach-Object {
$_ | Add-Member -MemberType NoteProperty -Name Folder -Value $Folder; $_
}
I would, however suggest a slightly different approach. Since you're filtering the object properties later on anyway you could directly pipe the ACEs into the Select-Object cmdlet and add the path with a calculated property:
Get-Content $InputFile | % {
$Folder = $_
(Get-Acl $Folder).Access |
Select-Object #{n='Folder';e={$Folder}}, IdentityReference,
FileSystemRights, IsInherited
} | ? {
$_.Folder -ne $null -and
$_.IdentityReference -like "HARRAHS*" -and
$_.IsInherited -ne 'True'
} | Export-CSV $OutputFile -NoTypeInformation
Related
This script runs fine but I don't know how to add something like to get just 2022 last edited files only like {where LastWriteTime -eq 2022}
$arr = #()
gci 'C:\Users\myusername\Documents\' -recurse | ? {$_.PSIsContainer -eq $False} | % {
$obj = New-Object PSObject
$obj | Add-Member NoteProperty Directory $_.DirectoryName
$obj | Add-Member NoteProperty Name $_.Name
$obj | Add-Member NoteProperty Length $_.Length
$obj | Add-Member NoteProperty CreationTime $_.CreationTime
$obj | Add-Member NoteProperty Access $_.LastAccessTime
$obj | Add-Member NoteProperty Owner ((Get-ACL $_.FullName).Owner)
$arr += $obj
}
$arr | Export-CSV -notypeinformation "C:\Users\myusername\Downloads\report.csv"
LastWriteTime is a DateTime instance, hence you can simply check the Year property and compare against it. As for your code, 3 recommendations:
Use -File or -Directory when needing to filter by any of them.
Use PSCustomObject to instantiate your objects. It's easier and faster.
Avoid adding elements += to a fixed collection #(). You can take full advantage of the pipeline in this case, get the files one by one, process each object and output them to a file.
Get-ChildItem 'C:\Users\myusername\Documents\' -Recurse -File | ForEach-Object {
if($_.LastWriteTime.Year -eq 2022) {
[pscustomobject]#{
Directory = $_.DirectoryName
Name = $_.Name
Length = $_.Length
CreationTime = $_.CreationTime
Access = $_.LastAccessTime
Owner = (Get-ACL $_.FullName).Owner
}
}
} | Export-CSV "C:\Users\myusername\Downloads\report.csv" -NoTypeInformation
Santiago's helpful answer contains an effective solution and explains the problems with your approach well.
Let me complement it with an alternative solution that uses the Where-Object cmdlet to perform the desired filtering first, and the Select-Object cmdlet with calculated properties to get the desired property names and values to pass to Export-Csv:
Get-ChildItem -File C:\Users\myusername\Documents -recurse |
Where-Object { $_.LastWriteTime.Year -eq 2022 } |
Select-Object #{ Name='Directory'; Expression = { $_.DirectoryName } },
Name,
Length,
CreationTime,
#{ Name='Access'; Expression = { $_.LastAccessTime } },
#{ Name='Owner'; Expression = { (Get-ACL $_.FullName).Owner } } |
Export-CSV -notypeinformation "C:\Users\myusername\Downloads\report.csv"
Im quite new with powershell and I need to do a shared folders permission report. I've the following code:
$path = \\server\shared_folder
dir $path | where { $_.PsIsContainer } | % { $path1 = $_.fullname; Get-Acl $_.Fullname | % { $_.access | Add-Member -MemberType NoteProperty '.\Application Data' -Value $path1 -passthru }} | Export-Csv $reportpath
But the output is:
\\server\shared_folder\folder1;FileSystemRights;AccessControlType;IsInherited;InheritanceFlags;PropagationFlags
\\server\shared_folder\folder2;FileSystemRights;AccessControlType;IsInherited;InheritanceFlags;PropagationFlags
I need the following output:
\\server\shared_folder;FileSystemRights;AccessControlType;IsInherited;InheritanceFlags;PropagationFlags
Why is doing the "dir" recursiveley if I do not specify it? If I am specifying where im telling to do so?
To get the exact answer you are asking for:
$path = "\\server\shared_folder"
dir $path | where { $_.PsIsContainer } | % { $path1 = $_.Root; Get-Acl $_.Fullname | % { $_.access | Add-Member -MemberType NoteProperty '.\Application Data' -Value $path1 -passthru }} | Export-Csv $reportpath
Notice the "$_.Root" after the ForEach-Object (%). But in my opinion the following is better because this way you see the foldername under '.\Application Data':
$path = "\\server\shared_folder"
dir $path | where { $_.PsIsContainer } | % { $path1 = $_.Name; Get-Acl $_.Fullname | % { $_.access | Add-Member -MemberType NoteProperty '.\Application Data' -Value $path1 -passthru }} | Export-Csv $reportpath
Hope this helps, because your question is not very clear imo.
Also please do yourself a favour and write the code in PowerShell ISE and use the PowerShell StyleGuide guidelines:
$path = "\\server\shared_folder"
$shares = Get-ChildItem $path | Where-Object { $_.PsIsContainer }
$data = foreach($share in $shares){
$path = $share.Name
$acls = Get-Acl $share.Fullname
foreach($acl in $acls){
$acl.access | Add-Member -MemberType NoteProperty '.\Application Data' -Value $path -passthru
}
}
$data | Export-Csv $reportpath
This makes the code readable and makes it easier to troubleshoot or modify the code later on. This version does not output ChildItems of the folders inside the shared folder. Only the folders placed inside "\server\shared_folder".
I have files in E:\MyFiles\ and E:\MyFiles\August. I am using PowerShell to store the file paths in a csv file (E:\CSVPaths.csv).
This is my script:
$exclude = #(".html", ".tt", ".xaml", ".csproj", ".sln", ".xml", ".cmd", ".txt",".svn")
"DirectoryPath, SourceFileName" | Out-File -FilePath "E:\CSVPaths.csv" -Encoding ASCII
$table = (get-childitem -recurse "E:\MyFiles" -File -ErrorAction SilentlyContinue | Where-Object { $exclude -notcontains $_.Extension }).Fullname
foreach ($row in $table)
{
$file=Get-ChildItem -recurse $row
$fileObject = new-object PSObject
$fileObject | add-member -membertype NoteProperty -name "DirectoryPath" -Value $file.DirectoryName
$fileObject | add-member -membertype NoteProperty -name "SourceFileName" -Value $file.Name
$newrow=$fileObject
Export-Csv "E:\CSVPaths.csv" -inputobject $newrow -append -Force
}
In both E:\MyFiles and E:\MyFiles\August folders, there are files with same name (example: Audit_Report.csv). While exporting to csv they are stored as System.Object[] in DirectoryPath and SourceFileName which is shown below:
DirectoryPath SourceFileName
System.Object[] System.Object[]
E:\MyFiles\August Audit_Report.csv
Please help to fix this issue.
There is no need to use a loop to get the output your after AFAICS.
$exclude = #(".html", ".tt", ".xaml", ".csproj", ".sln", ".xml", ".cmd", ".txt",".svn")
"DirectoryPath, SourceFileName" | Out-File -FilePath "E:\CSVPaths.csv" -Encoding ASCII
Get-ChildItem -recurse "E:\MyFiles" -File -ErrorAction SilentlyContinue |
Where-Object { $exclude -notcontains $_.Extension } |
Select-Object #{n="SoureFileName";e={$_.Name}},#{n="DirectoryPath";e={$_.DirectoryName}} |
Export-csv "E:\CSVPaths.csv" -Force -NoTypeInformation
# NB: The "-NoTypeInformation" is an assumption - remove if you what type info.
I am writing a script that will iterate through folders, grabbing substrings of the folder names as variable values, and then iterate through the log files in each of the folders and get some data out of the log files for output to a .csv file. Where I am running into an issue is with the use of Get-ChildItem with variables I have already set. When I run this line by itself, it does not provide any value:
#running this to see the value of $files
$files = Get-ChildItem $_.FullName $folder
$files does not then contain any value.
Here is the entire portion of the script, for reference and context:
#get all folders from the Logs directory
$folders = Get-ChildItem "C:\Temp\MPOS\Logs"
#iterate through each folder
foreach ($folder in $folders) {
#set substrings of the folder name to variables
$storeNumber = $folder.Name.Substring(2,3)
$date = $folder.Name.Substring(9,7)
#get all files from the current folder being evaluated
$files = Get-ChildItem $_.FullName $folder
#iterate through each file in the current folder
foreach ($file in $files) {
#set substring of the file name to a variable
$registerNumber = $file.Name.Substring(12,4)
#get content of the file
$logfileContent = Get-Content $file
#look for all matches of the string "TransactionNumber"
$transactions = Select-String -InputObject $logfileContent -Pattern "TransactionNumber" -AllMatches
#count number of matches from above
$transactionCount = $transactions.Matches.Count
#below info is creating the object for the .csv
$transObject = New-Object PSObject
$transObject | Add-Member -MemberType NoteProperty -Name "StoreNumber" -Value $storeNumber
$transObject | Add-Member -MemberType NoteProperty -Name "Sales Date" -Value $date
$transObject | Add-Member -MemberType NoteProperty -Name "RegisterNumber" -Value $registerNumber
$transObject | Add-Member -MemberType NoteProperty -Name "Transactions" -Value $transactionCount
$resultsArray += $transObject
}
}
$resultsArray | Export-Csv C:\Temp\MPOS\MPOSTransactions.csv -NoTypeInformation
Edited code below - changed to read $folder.FullName - working now!
$resultsArray = #()
$folders = Get-ChildItem "C:\Temp\MPOS\Logs"
foreach ($folder in $folders) {
$storeNumber = $folder.Name.Substring(2,3)
$date = $folder.Name.Substring(9,7)
$files = Get-ChildItem $folder.FullName
foreach ($file in $files) {
$registerNumber = $file.Name.Substring(12,4)
$logfileContent = Get-Content $file.FullName
$transactions = Select-String -InputObject $logfileContent -Pattern "TransactionNumber" -AllMatches
$transactionCount = $transactions.Matches.Count
$transObject = New-Object PSObject
$transObject | Add-Member -MemberType NoteProperty -Name "StoreNumber" -Value $storeNumber
$transObject | Add-Member -MemberType NoteProperty -Name "Sales Date" -Value $date
$transObject | Add-Member -MemberType NoteProperty -Name "RegisterNumber" -Value $registerNumber
$transObject | Add-Member -MemberType NoteProperty -Name "Transactions" -Value $transactionCount
$resultsArray += $transObject
}
}
$resultsArray | Export-Csv C:\Temp\MPOS\MPOSTransactions.csv -NoTypeInformation
I had this exact issue, but I found out in my case I was trying to load a variable by piping in a value that also was using Format-Table command.
Example: (this worked)
$GetMostRecentFile = $GetLatestFile = Get-ChildItem -Force -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $.LastWriteTime.Date -lt (Get-Date).Date -and $.Name -ne 'Thumbs.db' -and $_.Name -ne '.DS_Store'} | Sort LastWriteTime -Descending | Select-Object -First 1 LastWriteTime,FullName,Length
(this didn't work)
$GetLatestFile = Get-ChildItem -Force -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $.LastWriteTime.Date -lt (Get-Date).Date -and $.Name -ne 'Thumbs.db' -and $_.Name -ne '.DS_Store'} | Sort LastWriteTime -Descending | Select-Object -First 1 LastWriteTime,FullName,Length | Format-Table -Wrap
Because I'd been using Format-Table as part of my commands to explore this data and build my queries, I forgot that if you pipe this (with FT) to a variable, the variable won't have the details.
In my case above, I needed to pull $GetMostRecentFile.FullName and $GetMostRecentFile.LastWriteTime pulled into another array. But when I was piping with FT, there was not $GetMostRecentFile.FullName. When I remove
I'm trying to write a PowerShell script retrieving the directory size and owner on my Windows file systems. I've got two separate scripts that work independently, but I don’t know how to put them together as a single script file.
Directory Name and Size:
$startFolder = "C:\Test”
$colItems = (Get-ChildItem $startFolder | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object)
foreach ($i in $colItems)
{
$subFolderItems = (Get-ChildItem $i.FullName | Measure-Object -property length -sum)
$i.FullName + " -- " + "{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB"
}
Directory owner:
Get-ACL C:\Test
I'd like for the script to output to a CSV file.
So something along the lines of this then?
$start = "c:\temp"
$output = "C:\temp\output.csv"
Get-ChildItem $start | Where-Object{$_.PSIsContainer} | ForEach-Object{
$singleFolder = $_.FullName
$folderSize = Get-ChildItem $singleFolder -Recurse -Force | Where-Object{!$_.PSIsContainer} | Measure-Object -Property length -sum | Select-Object -ExpandProperty Sum
$folderSize = [math]::round($folderSize/1MB, 2)
$owner = Get-Acl $singleFolder | Select-Object -ExpandProperty Owner
$_ | Add-Member -MemberType NoteProperty -Name FolderSize -Value $folderSize -PassThru |
Add-Member -MemberType NoteProperty -Name Owner -Value $owner -PassThru
} | Select-Object FullName,FolderSize,Owner | Export-Csv $output -NoTypeInformation
Needed to add some extra logic in length calculation to keep folders out of the mix > Where-Object{!$_.PSIsContainer}. This should work with PowerShell 2.0 just fine.
It loops through each folder in the root of $start and for each $singleFolder calculates the size of the contents and folder owner.
The variables are then added to object through pipeline with Add-Member as the properties FolderSize and Owner. The final Select-Object is used to isolate the properties we want for the output file.
Sample
FullName FolderSize Owner
-------- ---------- -----
C:\temp\37 Place i.Bay domain\guy
C:\temp\adoc42 1103186357 domain\guy
C:\temp\Adoc72 958330505 domain\guy
Notice the empty folder. That output is sent to Export-CSV in the file $output