347

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?

10 Answers 10

538

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

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse -ErrorAction SilentlyContinue -Force
10
  • 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
    Commented Jun 20, 2013 at 11:24
  • 6
    Try to set the ErrorAction parameter to Continue or SilentlyContinue (in case its value is not as mentioned).
    – Shay Levy
    Commented Jun 20, 2013 at 11:56
  • 38
    A shorter way of doing exactly the same thing: cd V:\MyFolder followed by ls -r -inc CopyForBuild.bat Commented Aug 14, 2014 at 21:57
  • 16
    So what the commenters above mean is... ls -r -ea silentlycontinue -fo -inc "filename.txt" | % { $_.fullname }
    – Andrew
    Commented Nov 4, 2017 at 7:34
  • 2
    To add to the comments: The diff between filter and inc is explained here. -fo could be force. % is an alias for foreach-object
    – Timo
    Commented Jul 8, 2020 at 14:53
81

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}
4
  • 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. Commented Aug 1, 2017 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
    Commented Nov 15, 2018 at 10:15
  • As a beginner, I am having troubles understanding what is going on after the pipe. I've opened a question about it. Commented Mar 10, 2021 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. Commented Apr 8, 2021 at 7: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
23

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
18
Get-ChildItem V:\MyFolder -name -recurse *.CopyForbuild.bat

Will also work

2
  • And if you want to output results to a file, you can add ` > path_to_filename.txt` at the end of the command.
    – Gwen Au
    Commented Oct 10, 2019 at 3:20
  • for current directory Get-ChildItem . -name -recurse *.bat worked for me
    – cmhughes
    Commented Nov 17, 2021 at 7:59
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' }
1
  • 1
    Shouldn't it be '\ACopyForBuild\.(bat|cmd)\Z'?
    – E. Sundin
    Commented Mar 18, 2019 at 15:09
7

Try this:

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse | Where-Object { $_.Attributes -ne "Directory"}
1
  • 2
    You can also use | Where-Object { !$_PSIsContainer } to exclude folders
    – Gargravarr
    Commented Jun 17, 2016 at 11:23
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.

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.

1
  • Not sure why this system blocked me from adding comments. Commented May 27, 2023 at 18:28
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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.