212

I need to get all the files including the files present in the subfolders that belong to a particular type.

I am doing something like this, using Get-ChildItem:

Get-ChildItem "C:\windows\System32" -Recurse | where {$_.extension -eq ".txt"}

However, it's only returning me the files names and not the entire path.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gagan
  • 5,416
  • 13
  • 58
  • 86

15 Answers15

301

Add | select FullName to the end of your line above. If you need to actually do something with that afterwards, you might have to pipe it into a foreach loop, like so:

get-childitem "C:\windows\System32" -recurse | where {$_.extension -eq ".txt"} | % {
     Write-Host $_.FullName
}
Chris N
  • 7,239
  • 1
  • 24
  • 27
145

This should perform much faster than using late filtering:

Get-ChildItem C:\WINDOWS\System32 -Filter *.txt -Recurse | % { $_.FullName }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shay Levy
  • 121,444
  • 32
  • 184
  • 206
  • 21
    This is true. A caveat: this command actually gets files like `*.txt*` (`-Filter` uses CMD wildcards). If this is not what you want then use `-Include *.txt`. – Roman Kuzmin Oct 30 '12 at 06:14
  • `ls | % { $_.FullName }` to get full path in file listing ; assuming alias ls=Get-ChildItem – Mathieu CAROFF Jan 27 '22 at 18:45
47

You can also use Select-Object like so:

Get-ChildItem "C:\WINDOWS\System32" *.txt -Recurse | Select-Object FullName
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
imlokesh
  • 2,506
  • 2
  • 22
  • 26
  • 7
    Note that `Select-Object` returns `PSCustomObject`, not a string. It might not work if you use result as parameter for another program – sad comrade Aug 25 '15 at 20:08
  • 9
    Yes to what @Chintsu said. To get strings instead of `PSCustomObject`, use `-ExpandProperty FullName` instead of simply `FullName`. As far as I understand, `-ExpandProperty` parameter causes the cmdlet to return the results as the specified property's (native?) type instead of as some custom object. – doubleDown Feb 22 '16 at 06:22
  • I needed time too (I'd messed with the source of a program and thought later that I should probably have started source control on it, but I can get an idea of my first commit against "master" by getting files since installation: `Get-ChildItem -Path 'C:\Program Files\TheProgram' -Recurse | Where-Object -FilterScript {($_.LastWriteTime -gt '2020-03-01')} | Select-Object FullName` – Neil Gaetano Lindberg Mar 05 '20 at 19:01
32

Here's a shorter one:

(Get-ChildItem C:\MYDIRECTORY -Recurse).fullname > filename.txt
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JustAGuy
  • 5,151
  • 11
  • 41
  • 55
14

If relative paths are what you want you can just use the -Name flag.

Get-ChildItem "C:\windows\System32" -Recurse -Filter *.txt -Name

Polymorphix
  • 1,066
  • 1
  • 12
  • 29
  • This doesn't seem to give the relative path, only the filename. Could you provide an example? – Omar Saad Jun 16 '21 at 11:19
  • 2
    If the file is in the folder you start in, it only shows the filename. If it is in a subfolder it will give `subfolder/file.txt` – Polymorphix Jun 18 '21 at 06:47
  • -Name only gives the filename, not the path – diek Dec 07 '22 at 17:06
  • No, it gives the relative path, as stated in my answer and in my previous comment. It's not exactly what the OP asked for, but can be a useful supplement. – Polymorphix Dec 21 '22 at 08:27
8
Get-ChildItem -Recurse *.txt | Format-Table FullName

That is what I used. I feel it is more understandable as it doesn't contain any loop syntax.

Mandrake
  • 1,161
  • 1
  • 10
  • 11
8

I used this line command to search ".xlm" files in "C:\Temp" and the result print fullname path in file "result.txt":

(Get-ChildItem "C:\Temp" -Recurse | where {$_.extension -eq ".xml"} ).fullname > result.txt 

In my tests, this syntax works beautiful for me.

7

Try this:

Get-ChildItem C:\windows\System32 -Include *.txt -Recurse | select -ExpandProperty FullName
Uwe Allner
  • 3,399
  • 9
  • 35
  • 49
7

Really annoying thing in PS 5, where $_ won't be the full path within foreach. These are the string versions of FileInfo and DirectoryInfo objects. For some reason a wildcard in the path fixes it, or use Powershell 6 or 7. You can also pipe to get-item in the middle.

Get-ChildItem -path C:\WINDOWS\System32\*.txt -Recurse | foreach { "$_" }

Get-ChildItem -path C:\WINDOWS\System32 -Recurse | get-item | foreach { "$_" }

This seems to have been an issue with .Net that got resolved in .Net Core (Powershell 7): Stringification behavior of FileInfo / Directory instances has changed since v6.0.2 #7132

js2010
  • 23,033
  • 6
  • 64
  • 66
5

This worked for me, and produces a list of names:

$Thisfile=(get-childitem -path 10* -include '*.JPG' -recurse).fullname

I found it by using get-member -membertype properties, an incredibly useful command. most of the options it gives you are appended with a .<thing>, like fullname is here. You can stick the same command;

  | get-member -membertype properties 

at the end of any command to get more information on the things you can do with them and how to access those:

get-childitem -path 10* -include '*.JPG' -recurse | get-member -membertype properties
T3 H40
  • 2,326
  • 8
  • 32
  • 43
L1ttl3J1m
  • 385
  • 5
  • 8
3
gci "C:\WINDOWS\System32" -r -include .txt | select fullname
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vuong Doan
  • 31
  • 1
  • 6
    Could you please elaborate more your answer adding a little more description about the solution you provide? – abarisone Sep 11 '15 at 08:53
3

I am using below script to extact all folder path:

Get-ChildItem -path "C:\" -Recurse -Directory -Force -ErrorAction SilentlyContinue | Select-Object FullName | Out-File "Folder_List.csv"

Full folder path is not coming. After 113 characters, is coming:

Example - C:\ProgramData\Microsoft\Windows\DeviceMetadataCache\dmrccache\en-US\ec4d5fdd-aa12-400f-83e2-7b0ea6023eb7\Windows...
Unheilig
  • 16,196
  • 193
  • 68
  • 98
3

Why has nobody used the foreach loop yet? A pro here is that you can easily name your variable:

# Note that I'm pretty explicit here. This would work as well as the line after:
# Get-ChildItem -Recurse C:\windows\System32\*.txt
$fileList = Get-ChildItem -Recurse -Path C:\windows\System32 -Include *.txt
foreach ($textfile in $fileList) {
    # This includes the filename ;)
    $filePath = $textfile.fullname
    # You can replace the next line with whatever you want to.
    Write-Output $filePath
}
NostraDavid
  • 195
  • 8
  • how can I get the individual filepath of a textfile without using foreach textfile in fileList? something like textfile= $fileList[$i].fullname, I know is not the most optimal approach but I need to make it this way :( – Heber Solis Feb 17 '20 at 22:29
  • Just add a `$` in front of `textfile`: `$textfile = $fileList[$i].FullName`. Assuming `$i` has a numeric value, that is. – NostraDavid Jun 05 '20 at 14:48
1

[alternative syntax]

For some people, directional pipe operators are not their taste, but they rather prefer chaining. See some interesting opinions on this topic shared in roslyn issue tracker: dotnet/roslyn#5445.

Based on the case and the context, one of this approach can be considered implicit (or indirect). For example, in this case using pipe against enumerable requires special token $_ (aka PowerShell's "THIS" token) might appear distasteful to some.

For such fellas, here is a more concise, straight-forward way of doing it with dot chaining:

(gci . -re -fi *.txt).FullName

(<rant> Note that PowerShell's command arguments parser accepts the partial parameter names. So in addition to -recursive; -recursiv, -recursi, -recurs, -recur, -recu, -rec and -re are accepted, but unfortunately not -r .. which is the only correct choice that makes sense with single - character (if we go by POSIXy UNIXy conventions)! </rant>)

vulcan raven
  • 32,612
  • 11
  • 57
  • 93
  • 1
    Note to the rant: the `-r` short form of `-Recurse` works fine for me. – Polymorphix Apr 06 '16 at 08:33
  • @Polymorphix, you are right, it is working for me on Windows 10 (not sure which version I was trying earlier). However, same holds true with `-File` switch `-fi` in the sample: `-fil` and `-file` works, but not `-f`. Going by POSIX style, it should be `--file` (multi-letters) and `-f` (single-letter, unless -f is reserved for something else, say `force` switch, then it can be something else like `-l` or no single-letter option at all). – vulcan raven Apr 10 '16 at 18:39
0

I had an issue where I had an executable file which had directory path strings as parameters and the format. Like this:

"C:\temp\executable.exe" "C:\storage\filename" "C:\storage\dump" -jpg

I needed to execute this command across terabytes of .jpg files in different folders.

$files = Get-ChildItem  -Path C:\storage\*.jpg -Recurse -Force | Select-Object -ExpandProperty FullName

for ($i=0; $i -lt $files.Count; $i++) {
    [string]$outfile = $files[$i]
    
    Start-Process -NoNewWindow -FilePath "C:\temp\executable.exe" -ArgumentList $outfile, "C:\storage\dump", "-dcm"
   

}
Jonathan
  • 46
  • 3