323

I am searching for a file in all the folders.

Copyforbuild.bat is available in many places, and I would like to search recursively.

$File = "V:\Myfolder\**\*.CopyForbuild.bat"

How can I do it in PowerShell?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Samselvaprabu
  • 16,830
  • 32
  • 144
  • 230

10 Answers10

504

Use the Get-ChildItem cmdlet with the -Recurse switch:

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse -ErrorAction SilentlyContinue -Force
software is fun
  • 7,286
  • 18
  • 71
  • 129
Shay Levy
  • 121,444
  • 32
  • 184
  • 206
  • 2
    Seems to have an issue that if it runs into a directory you don't have permission to access, the entire search is aborted because the process exits. Is there a way around that? – deed02392 Jun 20 '13 at 11:24
  • 6
    Try to set the ErrorAction parameter to Continue or SilentlyContinue (in case its value is not as mentioned). – Shay Levy Jun 20 '13 at 11:56
  • 35
    A shorter way of doing exactly the same thing: `cd V:\MyFolder` followed by `ls -r -inc CopyForBuild.bat` – Orion Edwards Aug 14 '14 at 21:57
  • 14
    So what the commenters above mean is... `ls -r -ea silentlycontinue -fo -inc "filename.txt" | % { $_.fullname }` – Andrew Nov 04 '17 at 07:34
  • I adapted this answer to do partial string by adding the astric symbol (`*`) to the end of the filename. ****** LINE1: `$File = "Microsoft.OData.Core.NetFX35.V7*"` LINE2: `$Folder = "C:\Program Files"` LINE3:`Get-ChildItem -Path $Folder -Filter $File -Recurse -ErrorAction SilentlyContinue -Force` – SherlockSpreadsheets Apr 29 '19 at 15:21
  • 2
    To add to the comments: The diff between `filter` and `inc` is explained [here](https://stackoverflow.com/a/28603626/1705829). `-fo` could be `force`. `%` is an alias for `foreach-object` – Timo Jul 08 '20 at 14:53
  • @OrionEdwards -filter is 2-3x faster than -include. – js2010 Oct 18 '21 at 14:50
  • @deed02392 I didn't have this problem, at least in ps 5.1. – js2010 Oct 18 '21 at 14:51
  • @js2010 I'm pretty sure I was on PS 2.0 back in 2013 :-) – deed02392 Oct 19 '21 at 12:42
  • @OrionEdwards: `ls` gives me some `Access to the path '...' is denied` that `Get-ChildItem` don't, but I'm not sure if it is a good thing (it actually searches in said paths) or a bad thing (it does not search in said paths but don't raise an error). – gluttony Apr 28 '23 at 09:20
76

I use this to find files and then have PowerShell display the entire path of the results:

dir -Path C:\FolderName -Filter FileName.fileExtension -Recurse | %{$_.FullName}

You can always use the wildcard * in the FolderName and/or FileName.fileExtension. For example:

dir -Path C:\Folder* -Filter File*.file* -Recurse | %{$_.FullName}

The above example will search any folder in the C:\ drive beginning with the word Folder. So if you have a folder named FolderFoo and FolderBar PowerShell will show results from both of those folders.

The same goes for the file name and file extension. If you want to search for a file with a certain extension, but don't know the name of the file, you can use:

dir -Path C:\FolderName -Filter *.fileExtension -Recurse | %{$_.FullName}

Or vice versa:

dir -Path C:\FolderName -Filter FileName.* -Recurse | %{$_.FullName}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
BinaryJoe01
  • 1,141
  • 10
  • 12
  • 5
    I find this answer extremely useful because it addresses a particular use case - actually wanting to use the file that you are looking for. The | to the give you the full name of the file is something missing in the other answers. – Newteq Developer Aug 01 '17 at 15:17
  • 2
    I have to agree with @Sanity1123 here, if you actually want to use the file, you will need the full path to the file. IMHO this should be the accepted answer. – uceumern Nov 15 '18 at 10:15
  • As a beginner, I am having troubles understanding what is going on after the pipe. I've opened [a question](https://stackoverflow.com/questions/66566918/powershell-syntax) about it. – Daemon Painter Mar 10 '21 at 14:38
  • 1
    As other say, this is the best answer when you need to store the return value. In my case, I had to find a file to remove it, and this made it way easier. – xCovelus Apr 08 '21 at 07:40
34

When searching folders where you might get an error based on security (e.g. C:\Users), use the following command:

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse -ErrorAction SilentlyContinue -Force
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mötz
  • 1,682
  • 11
  • 17
21

Here is the method that I finally came up with after struggling:

Get-ChildItem -Recurse -Path path/with/wildc*rds/ -Include file.*

To make the output cleaner (only path), use:

(Get-ChildItem -Recurse -Path path/with/wildc*rds/ -Include file.*).fullname

To get only the first result, use:

(Get-ChildItem -Recurse -Path path/with/wildc*rds/ -Include file.*).fullname | Select -First 1

Now for the important stuff:

To search only for files/directories do not use -File or -Directory (see below why). Instead use this for files:

Get-ChildItem -Recurse -Path ./path*/ -Include name* | where {$_.PSIsContainer -eq $false}

and remove the -eq $false for directories. Do not leave a trailing wildcard like bin/*.

Why not use the built in switches? They are terrible and remove features randomly. For example, in order to use -Include with a file, you must end the path with a wildcard. However, this disables the -Recurse switch without telling you:

Get-ChildItem -File -Recurse -Path ./bin/* -Include *.lib

You'd think that would give you all *.libs in all subdirectories, but it only will search top level of bin.

In order to search for directories, you can use -Directory, but then you must remove the trailing wildcard. For whatever reason, this will not deactivate -Recurse. It is for these reasons that I recommend not using the builtin flags.

You can shorten this command considerably:

Get-ChildItem -Recurse -Path ./path*/ -Include name* | where {$_.PSIsContainer -eq $false}

becomes

gci './path*/' -s -Include 'name*' | where {$_.PSIsContainer -eq $false}
  • Get-ChildItem is aliased to gci
  • -Path is default to position 0, so you can just make first argument path
  • -Recurse is aliased to -s
  • -Include does not have a shorthand
  • Use single quotes for spaces in names/paths, so that you can surround the whole command with double quotes and use it in Command Prompt. Doing it the other way around (surround with single quotes) causes errors
Asad-ullah Khan
  • 1,573
  • 18
  • 22
18
Get-ChildItem V:\MyFolder -name -recurse *.CopyForbuild.bat

Will also work

rink.attendant.6
  • 44,500
  • 61
  • 101
  • 156
user3303020
  • 933
  • 2
  • 12
  • 26
8

Filter using wildcards:

Get-ChildItem -Filter CopyForBuild* -Include *.bat,*.cmd -Exclude *.old.cmd,*.old.bat -Recurse

Filtering using a regular expression:

Get-ChildItem -Path "V:\Myfolder" -Recurse
| Where-Object { $_.Name -match '\ACopyForBuild\.[(bat)|(cmd)]\Z' }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MovGP0
  • 7,267
  • 3
  • 49
  • 42
7

Try this:

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse | Where-Object { $_.Attributes -ne "Directory"}
ZoogieZork
  • 11,215
  • 5
  • 45
  • 42
Sevenfold
  • 71
  • 1
  • 1
2

To add to @user3303020 answer and output the search results into a file, you can run

Get-ChildItem V:\MyFolder -name -recurse *.CopyForbuild.bat > path_to_results_filename.txt

It may be easier to search for the correct file that way.

Gwen Au
  • 859
  • 9
  • 10
0

On a Windows system: Search for all .py files in the 'c:\temp' dir and subdirs, type: dir -r *.py or dir *.py -r

On a *Nix (Linux / MacOs system: at the terminal type: find /temp -name *.py

This works fine for me.

0

Generally, robocopy is the fastest and simplest way for searching multiple files in parallel threads. It needs a quite good Powersell code with parallelism to beat that. Here is a link to an article I have written in the past with all the different options you have: Fastest way to find a full path of a given file via Powershell? Check the accepted answer for the best code.

Carsten
  • 1,612
  • 14
  • 21