Powershell: Using Get-ChildItem with variables - powershell

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

Related

Get shared folder permissions

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

PowerShell: trying to print path of file if string found

I am trying to print the path of a file if string is found. Problem is if 1 file does not contain the string in a folder then I do not get any output. Basically I am looking to see if a certificate epoch-time is within 30 days of expiration. Below is my code:
$c = Get-Date (Get-Date).ToUniversalTime() -UFormat %s
$epochtimes=[math]::Round($c)
$d = get-childitem C:\scripts\PALO\* -recurse | Select-String -pattern
"expiry-epoch"
$e=$d -split "epoch"
$certtime=[double] $e[1]
$certexp = $certtime - 2592000
ForEach ($i in $certexp){
If ($certexp -le $epochtime) {
Write-Host $i
}
}
I've made a couple of assumptions since it isn't totally clear from your question what is going on. Importantly, I've assumed you have a directory tree containing some text files each with a line in it like this:
expiry-epoch 1526854766.33933
If this is the case, then the following should display some useful information about the files:
Get-ChildItem -Path "C:\test" -File -Recurse |
ForEach-Object {$threshold = [Math]::Round((Get-Date (Get-Date).ToUniversalTime() -UFormat %s)) + 2592000} {
$certEpochTime = ([double]($_ | Select-String -Pattern "^expiry-epoch (\d+\.\d+)$").Matches.Groups[1].Value)
$certExpiryTime = (Get-Date "1/1/1970").AddSeconds($certEpochTime)
New-Object -TypeName PsCustomObject|
Add-Member -MemberType NoteProperty -Name ExpiresSoon -Value ($certEpochTime -le $threshold) -PassThru |
Add-Member -MemberType NoteProperty -Name DaysUntilExpiry -Value ([Math]::Round(($certExpiryTime - (Get-Date)).TotalDays)) -PassThru |
Add-Member -MemberType NoteProperty -Name CertExpiryTime -Value $certExpiryTime -PassThru |
Add-Member -MemberType NoteProperty -Name CertEpochTime -Value $certEpochTime -PassThru |
Add-Member -MemberType NoteProperty -Name FilePath -Value $_.FullName -PassThru
} | Format-Table -AutoSize
EDIT:
If all you need is the filename of any files with an expiry-epoch within 30 days, then this simplified version will do that:
Get-ChildItem -Path "C:\test" -File -Recurse |
ForEach-Object {$threshold = [Math]::Round((Get-Date (Get-Date).ToUniversalTime() -UFormat %s)) + 2592000} {
$certEpochTime = ([double]($_ | Select-String -Pattern "^expiry-epoch (\d+\.\d+)$").Matches.Groups[1].Value)
if($certEpochTime -le $threshold)
{
$_.FullName
}
}

System.Object[] - when file names are same

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.

Reading zip archive files for content

I created the following code, but it is not actually reading any of the .zip or .prd files as expected, but the other parts are working. Might you help me figure out why it is not actually reading the zip files in the ForEach loop?
#Set variables for subversion paths
$ScriptPath = (Split-Path $myinvocation.MyCommand.path -Parent)
#$Package = $ScriptPath
#Create folder for temporary copy of SVN directory
New-Item C:\MyTemp-type directory -ErrorAction SilentlyContinue -Force
New-Item C:\Results -type directory -ErrorAction SilentlyContinue -Force
Test-Path $profile
New-item –type file –force $profile
#Set variables for subversion paths
$CurrentSVNPath = "http://MySVNPath"
$TempSVNPath = "C:\MyTemp"
$ResultsFilePath = "C:\Results"
#Download a local copy of the SVN Repository
# Wait for command to finish before moving forward
#$SVNDownloadJob = Start-Job {SVN Checkout $CurrentSVNPath $TempSVNPath}
$SVNDownloadJob = Start-Job {TortoiseProc.exe /command:update /path:"C:\SVN_Repo" /closeonend:1 | Out-Null}
Wait-Job $SVNDownloadJob
Receive-Job $SVNDownloadJob
#Find pattern to search for within all files from where this script is run
#If you do not want to look for the standard pattern uncomment/comment the $Pattern variables
#$Pattern = Read-Host 'What pattern are you looing for?'
$Pattern = "Simulate=`"true`""
$SearchPattern = “Simulate=`”true`””
$PackageList = Get-ChildItem –Path $ScriptPath –Recurse –filter “*.zip, *.prd”
#Start searching all folders where this script exists for 'Simulate=true'
$k =foreach ($file in Get-ChildItem -Path $ScriptPath -Recurse | Select-String -pattern $Pattern | Select-Object -Unique path) {$file.path}
$k > "$($ResultsFilePath)\SimulateEqualsTrueZipFiles.txt"
Foreach ( $Package in $PackageList) {
Read-Archive -$_.Path -Format Zip | `
Where-Object { $_.Name -like "*.zip" } | `
Expand-Archive -PassThru | select-string $SearchPattern | Select-Object -Unique path {$file.path}
$k > "$($ResultsFilePath)\SimulateEqualsTrueZipFiles.txt"
}
You can get the contents of Zip Folder by using below cmdlets
$ZipFile="Path"
$AllFile=Get-ChildItem $ZipFile -Recurse -Filter '*.zip'
$ObjArray = #()
foreach ($item in $AllFile){
$FullName=$item.FullName
$RawFiles = [IO.Compression.ZipFile]::OpenRead($FullName).Entries
$FullPathName=$FullName+"\"+"$RawFile"
foreach($RawFile in $RawFiles) {
$object = New-Object -TypeName PSObject
$Object | Add-Member -MemberType NoteProperty -Name FileName -Value $RawFile.Name
$Object | Add-Member -MemberType NoteProperty -Name FullPath -Value $FullPathName
$Object | Add-Member -MemberType NoteProperty -Name CompressedLengthInKB -Value ($RawFile.CompressedLength/1KB).Tostring("00")
$Object | Add-Member -MemberType NoteProperty -Name UnCompressedLengthInKB -Value ($RawFile.Length/1KB).Tostring("00")
$Object | Add-Member -MemberType NoteProperty -Name FileExtn -Value ([System.IO.Path]::GetExtension($RawFile.FullName))
$Object | Add-Member -MemberType NoteProperty -Name ZipFileName -Value $zipfile
$ObjArray += $Object
}
}
Make sure dot net 4.5 is installed before running the above cmdlets.

Getting a list of timestamps of all files in a folder and its subfolder in PowerShell in Windows 10

I would like to get file tree in text format with all three exact timestamps of each object. I didn't find any utility which offers file tree with exact timestamps, so I decided to use PowerShell. Here is a piece of code which I have so far:
$items = #()
dir -Force | foreach {
$Name = $_.Name
$Creation = $_.CreationTimeUtc
$Modified = $_.LastWriteTimeUtc
$Accessed = $_.LastAccessTimeUtc
$Size = $_.Length
$i = New-Object -TypeName psobject
$i | Add-Member -MemberType NoteProperty -Name Name -Value $Name
$i | Add-Member -MemberType NoteProperty -Name CreatedDateUtc -Value $Creation
$i | Add-Member -MemberType NoteProperty -Name CreatedTimeUtc -Value $Creation.TimeOfDay
$i | Add-Member -MemberType NoteProperty -Name ModifiedDateUtc -Value $Modified
$i | Add-Member -MemberType NoteProperty -Name ModifiedTimeUtc -Value $Modified.TimeOfDay
$i | Add-Member -MemberType NoteProperty -Name AccessedDateUtc -Value $Accessed
$i | Add-Member -MemberType NoteProperty -Name AccessedTimeUtc -Value $Accessed.TimeOfDay
$i | Add-Member -MemberType NoteProperty -Name Size -Value $Size
$items += $i
}
$items | Format-Table
This code is far from perfect because it doesn't show so many file attributes and because it doesn't show subfolders. I couldn't include more file attributes because width of table is limited in PowerShell.
What I would like is modifying this code so that it includes subdirectories, more file properties and saves result in form of CSV file. Can this be done? And if so, how exactly? Thank you very much.
it doesn't show subfolders
To include subfolders, use the -Recurse switch with Get-ChildItem (alias dir):
Get-ChildItem -Recurse | ...
To save the results to CSV, use the Export-Csv cmdlet:
Get-ChildItem -Recurse |Export-Csv C:\path\to\new\file.csv -NoTypeInformation
If you want specific properties, use the Select-Object cmdlet before piping to Export-Csv:
Get-ChildItem -Recurse |Select-Object Name,CreationTimeUtc |Export-Csv C:\path\to\new\file.csv -NoTypeInformation
If you want the date formatted with more specific time information, put it in a calculated property:
Get-ChildItem -Recurse |Select-Object Name,#{Name='CreatedTimeUtc';Expression={$_.CreationTimeUtc.TimeOfDay}} |Export-Csv C:\path\to\new\file.csv -NoTypeInformation
You could also use a custom date format string:
Get-ChildItem -Recurse |Select-Object Name,#{Name='CreatedTimeUtc';Expression={'{0:HH:mm:ss.fff}' -f $_.CreationTimeUtc}} |Export-Csv C:\path\to\new\file.csv -NoTypeInformation