Site icon Jessitron

PowerShell equivalent of find

TL;DR: gci -r -fi <filename-pattern>

My favorite use of find in bash is to find files whose name matches a pattern. For instance, find all the jar files under this directory:

bash# find . -name '*.jar'

In PowerShell, there’s a program called “find” but it ain’t the same program.

Short Answer

Instead, use Get-ChildItem. The arguments are different.

Long version, which I would use in programs:

pwsh> Get-ChildItem -Recurse -Filter '*.jar'

or shorthand, for typing at the prompt:

pwsh> gci -r -fi *.jar

but I want regex

The -Filter command-line option here is an optimization. For programmatic filtering: use Get-ChildItem -Recurse to gather all the files under the current directory, and pipe them to a Where-Object (abbreviates to where) filter.

You can test properties, like matching the name against a regex:

gci -r | where Name -match '\.jar$'

like checking the size of the file, excluding too-small ones:

gci -r | where Length -gt 3000

like only the files I’ve looked at in the last hour:

gci -r | where LastAccessTime -gt (Get-Date).AddHours(-1)

In my PowerShell in Windows Terminal, I get tab-completion for the property names! This is based on the type of objects returned by the gci command before the pipe. Whoa cool!

For more flexibility, you can break into a code block, referencing the input with $_. How about… length greater than 3kb or else I wrote to it since a specific day:

gci -r | where { $_.Length -gt ( 3 * 1024 ) -or $_.LastWriteTime -gt "04/23/2020" }

but that’s so long

The query for “size is large enough or I’ve accessed it in the last hour” works in bash too (I think):

bash# find . -size +3k -o -amin +60

There are two reasons I like the PowerShell version better than bash’s find:

There’s one reason I like bash’s find better than PowerShell syntax:

I can type find . -name '*.jar' without thinking about it.

I have it memorized. It is familiar. That’s a property of me; it’s my shared history with bash that makes me productive in it, NOT its superiority.

So I don’t recommend going deep on bash. I recommend getting productive in PowerShell instead, because learning scales in a language with deep consistency.

Addendum: condense the output

The output of Get-ChildItem is a bunch of FileInfo objects. The default printing takes up a lot of room. You can get it to print the path (which is called FullName):

Get-ChildItem -Recurse -Include '*.json' | Select FullName

You can also get other properties from Select. To see them all, pipe to Get-Member instead. That lists available properties.

Exit mobile version