Powershell count file improvement.

Dear experts

Powershell script code below is working fine, now I want to improve this by adding a progress in % of searching, I know it needs to first count all the file and all the string, then add it as 100%, and then it begins to search and give me a output for the % of where script is searching.

I'm going to try search for the solutions too, just in case I'm adding this here as well.

Thanks

function Runscript {
  Param(
	[Parameter(Position=0, Mandatory=$True)][ValidateNotNullOrEmpty()]
	[String]$Folder,
	[Parameter(Position=1, Mandatory=$True)][ValidateNotNullOrEmpty()]
	[String]$Text
  )

    foreach ($result in (Get-ChildItem -Path $Folder -Recurse -File | Select-String -Pattern $Text)) {
        $obj = New-Object -TypeName PSObject
        $obj | Add-Member -MemberType NoteProperty -Name LWT -Value ((Get-Item -Path $result.path).LastWriteTime)
        $obj | Add-Member -MemberType NoteProperty -Name Path -Value $result.path
        $obj | Add-Member -MemberType NoteProperty -Name Line -Value $result.linenumber
        ForEach-Object {
        $obj | Select-Object Path, Line, LWT
        Write-Output $obj
        }
    }
    if ($result -eq $null) {write-host "Cannot find "$Text}
}

do {
    Runscript | out-host
    $response = read-host 'Research?'
} until ($response -ne 'Yes')

Open in new window

LVL 1
WeTiAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

oBdACommented:
Counter offer: use a script that starts returning results while still processing, instead of first collecting all results, and then writing them all at once. It's easier on the RAM, too.
And some more suggestions: functions in PS should always use the <Verb>-<Noun> syntax, with a <Verb> from the list by Get-Verb.
Whenever possible, use the same/existing argument names for the same purpose:
- "Path" instead of "Folder" - as in GetChildItem and a multitude of other cmdlets expecting a file system path
- "Pattern" instead of "Text" - as in the Select-String used; this is important, because this string is not a plain text, it's a regular expression.
Function Find-FileByPattern {
Param(
	[Parameter(Position=0, Mandatory=$True)][ValidateNotNullOrEmpty()]
	[String]$Path,
	[Parameter(Position=1, Mandatory=$True)][ValidateNotNullOrEmpty()]
	[String]$Pattern
)
	$Script:Results = $false
	Get-ChildItem -Path $Path -Recurse -File |
		Select-String -Pattern $Pattern |
		Select-Object -Property Path, LineNumber, @{n='LWT'; e={(Get-Item -Path $_.Path).LastWriteTime; $Script:Results = $true}}
	If (-not $Script:Results) {
		Write-Host "Cannot find '$($Pattern)'"
	}
}

Do {
	Find-FileByPattern
	$response = Read-Host 'Research?'
} Until ($response -ne 'Yes')

Open in new window

And note that your current script returns every file found twice; is that really intended?
WeTiAuthor Commented:
Thanks for the answer, no, I just want to rerun the script if $response is Yes. But I still want to see the processing time or anything that shows its running.
WeTiAuthor Commented:
I found out that you could use -PercentComplete switch for it, but I don't know how to use it yet.
Discover the Answer to Productive IT

Discover app within WatchGuard's Wi-Fi Cloud helps you optimize W-Fi user experience with the most complete set of visibility, troubleshooting, and network health features. Quickly pinpointing network problems will lead to more happy users and most importantly, productive IT.

oBdACommented:
With progress bar, but without "Percent Complete",  "Percent Complete" would require to first retrieve and store a list of all files found, which can take quite some time. As far as user experience goes, this would be rather counter-productive.
Depending on the search string, of course, this will already produce actual output, where a version with "Percent Complete" would still be busy scanning for the number of files, not to mention returning output.
Function Find-FileByPattern {
Param(
	[Parameter(Position=0, Mandatory=$True)][ValidateNotNullOrEmpty()]
	[String]$Path,
	[Parameter(Position=1, Mandatory=$True)][ValidateNotNullOrEmpty()]
	[String]$Pattern
)
	$Script:Results = $false
	Get-ChildItem -Path $Path -Recurse -File |
		Select-String -Pattern $Pattern |
		Select-Object -Property Path, LineNumber, @{n='LWT'; e={
			Write-Progress -Activity "Searching for '$($Pattern)'" -Status $_.Path
			(Get-Item -Path $_.Path).LastWriteTime
			$Script:Results = $true
		}}
	If (-not $Script:Results) {
		Write-Host "Cannot find '$($Pattern)'"
	}
	Write-Progress -Activity 'Done' -Status 'Done' -Completed
}

Do {
	Find-FileByPattern
	$response = Read-Host 'Research?'
} Until ($response -ne 'Yes')

Open in new window

WeTiAuthor Commented:
Now I want script to count first all the files in the Path and it provide a total file number then it will count down, when it goes through everything, this is just for the user to see that the script is running... a output feedback....
WeTiAuthor Commented:
$countpath = Write-Host @( Get-ChildItem $Path ).Count;
This first count all files in the path, and then this $countpath will be 100% then it be a array there begin with 0 and to 100%
oBdACommented:
The way to do that is trivial.
What I'm trying to convey here is that obtaining the file count will
- Reduce the user experience, because it takes additional time to retrieve the file count - time that would be better spent returning results.
- Depending on the number of files searched, largely increase the memory footprint.
- Since you seem to be concerned about running time - Write-Progress will slow down the script all by its lonesome.
There will be nothing positive about it except for a tiny bit of eye candy, but objective drawbacks.
But whatever makes you happy ...
Function Find-FileByPattern {
Param(
	[Parameter(Position=0, Mandatory=$True)][ValidateNotNullOrEmpty()]
	[String]$Path,
	[Parameter(Position=1, Mandatory=$True)][ValidateNotNullOrEmpty()]
	[String]$Pattern
)
	$Script:Results = $false
	$AllItems = Get-ChildItem -Path $Path -Recurse -File | Select-Object -Property Fullname, LastWriteTime
	$Index = 0
	$AllItems | ForEach-Object {
		$item = $_
		Write-Progress -Activity "Searching for '$($Pattern)'" -Status $item.FullName -PercentComplete ((100 * $Index++) / $AllItems.Count)
		Select-String -Path $item.FullName -Pattern $Pattern |
			Select-Object -Property Path, LineNumber, @{n='LWT'; e={
				$item.LastWriteTime
				$Script:Results = $true
			}}
	}
	If (-not $Script:Results) {
		Write-Host "Cannot find '$($Pattern)'"
	}
	Write-Progress -Activity 'Done' -Status 'Done' -Completed
}

Do {
	Find-FileByPattern
	$response = Read-Host 'Research?'
} Until ($response -ne 'Yes')

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
random0Commented:
I use indexof when i want to know where i am within a foreach loop.

Example 1
$numbers = (5, 10, 15, 20, 25, 30, 35, 40, 45, 50)

foreach($n in $numbers){
($numbers.IndexOf($n) + 1) / $numbers.Count * 100

}

Open in new window


Example 2
$numbers2 = foreach($a in 1..1000) {$a}

foreach($n2 in $numbers2){
if((($numbers2.IndexOf($n2) + 1) / 100) -is [System.Int32]){
($numbers2.IndexOf($n2) + 1) / $numbers2.Count * 100
}

}

Open in new window

aikimarkCommented:
What is the nature of the $Text parameter?  I wonder if you might use the -include or -filter parameter of Get-ChildItem

In order to get an accurate count of the number of files, you might have to apply this filter.
WeTiAuthor Commented:
Yeah, that is what Im after, I understand that will reduce the performer of searching, but users really need to see the progress of that file searching, or they will just see a blank space that they will wondering what is going on... Thanks oBdA. You are the best.
WeTiAuthor Commented:
Question of the script if you got time to answer:
$Script:Results = $false
and $Script:Results = $true
-not $Script:Results
Lets see if I understand this right: $Script:Results = $false is when script didn't run, and $Script:Results = $true is when script is running, and if there is no $Script:Results value then write host right?
Why are you need this: $item = $_
Write-Progress -Activity "Searching for '$($Path)'" this $($Path), is this because you need to show the variable $Path in the text?
(100 * $Index++) is this 100 multiply with index+1? Index is 0 then when it found file, it will become 2...3...4? I don't understand this.
oBdACommented:
$Script:Results is used to determine if any results were found. It will be set to $true when an item is found, and needs to have a script scope because it'll be set inside a calculated property.
$item = $_ is required because because the LastWriteTime property is required inside the results from Select-String. At this point, the current pipeline variable $_ contains only the results from Select-String, not the file item anymore.
$($Pattern) is $Pattern inside a subexpression. Syntactically, the subexpression is not required since a regular variable is addressed, but I prefer to consistently access variables inside strings using a subexpression, whether required or not.
$Variable++ means that the variable will be incremented after whatever operation it's used in.
This would be the same as "100 * $Index; $Index = $Index + 1"
This, btw.,  is stuff you can just try for yourself by dropping into a PS console to see how it works.
100 * $Index++
$Index
100 * $Index++
$Index

Open in new window

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.