48

I'm trying to get a list of all the XSL and XSLT files in a directory.

dir -recurse -filter *.xsl,*.xslt -name

But the following error:

Get-ChildItem : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Filter'. Specified method is not supported.

dir -recurse -filter *.xsl -filter *.xslt -name

But got this error:

Get-ChildItem : Cannot bind parameter because parameter 'Filter' is specified more than once. To provide multiple values to parameters that can accept multiple values, use the array syntax. For example, "-parameter value1,value2,value3".

Can I list both file extensions with a single command?

1

6 Answers 6

57
dir .\* -include ('*.xsl', '*.xslt') -recurse
3
  • 3
    Note that the () is actually redundant, but I prefer to be explicit.
    – EBGreen
    Aug 2, 2011 at 18:25
  • 6
    It makes absolutely no sense why this command does not work without the -recurse switch, to list .xsl and .xslt files in the current directory. Jun 22, 2017 at 14:50
  • 1
    the answer by crysman is faster superuser.com/a/1056648/440382
    – crysman
    Mar 3, 2020 at 8:53
34

I do not know why, but this one seems to be much faster:

dir .\ -recurse | where {$_.extension -in ".xsl",".xslt"}
1
13

The "filters" *.xsl and *.xslt can be part of the path parameter as well. Path can take a string array:

Set-Location c:\topLevel
gci *.xsl, *.xslt -Recurse

If you want to specify a path other than the current location, or search multiple locations, create a couple of string arrays and use Join-Path to create an array of paths:

PS C:\> $paths   = 'c:\topLevel' , 'd:\topLevel'
PS C:\> $filters = '*.xsl' , '*.xslt'
PS C:\> $filters | ForEach-Object { Join-Path $paths $_ }
c:\topLevel\*.xsl
d:\topLevel\*.xsl
c:\topLevel\*.xslt
d:\topLevel\*.xslt
PS C:\>

That output can be piped to Get-ChildItem:

$paths   = 'c:\topLevel' , 'd:\topLevel'
$filters = '*.xsl' , '*.xslt'
$filters | % { Join-Path $paths $_ } | gci -name

Bonus Tip:

If you don't need the additional properties of the FileInfo objects, but just a list of fully qualifed paths, Resolve-Path is faster:

$paths   = 'c:\topLevel' , 'd:\topLevel'
$filters = '*.xsl' , '*.xslt'
$filters | % { Join-Path $paths $_ } | Resolve-Path

MY quick test:

PS C:\>Measure-Command { $filters | % { Join-Path $path $_ } | gci | select -expand FullName }

...
TotalMilliseconds : 31.2376



PS C:\>Measure-Command { $filters | % { Join-Path $path $_ } | Resolve-Path }

...
TotalMilliseconds : 12.2536
2

The question: 'I'm trying to get a list of all the XSL and XSLT files in a directory.'

This is a simpler approach:

Get-ChildItem * -Recurse -File | Where-Object { $_.Name -like "*.XSL*" }

which will get all .xsl and .xslt files.

Additionally, you can add ' -OR ( $_.Name -like "search string" ) inside the braces if you wanted to look for two different strings at the same time, like so:

Get-ChildItem * -Recurse -File | Where-Object { ($_.Name -like "string 1") -OR ( $_.Name -like "string 2") }
1

This is older, but it helped me write this script to update URL's in desktop and/or favorite shortcuts, so I thought I would share:

foreach ($link in GCI "$env:USERPROFILE\Desktop" | Where-Object {$_.extension -in '.lnk','.url'}) {
   $shell = New-Object -COM WScript.Shell
   $shortcut = $shell.CreateShortcut($link.FullName)
   $shortcut.TargetPath = $shortcut.TargetPath -replace "old-url.com","new-url.com"
   $shortcut.Save()
}

foreach ($link in GCI "$env:USERPROFILE\Favorites" | Where-Object {$_.extension -in '.lnk','.url'}) {
   $shell = New-Object -COM WScript.Shell
   $shortcut = $shell.CreateShortcut($link.FullName)
   $shortcut.TargetPath = $shortcut.TargetPath -replace "old-url.com","new-url.com"
   $shortcut.Save()
}
1

I had the same question and I wanted to avoid using any -Include or -Recurse:

# Declare your base/common path:
$Path = 'C:\Xpto\123'

# Because -Filter will not accept a list, create a list
# that contains all the variations you need, and instead
# provide the list to -Path.
# Note: Requires double quotes instead of single:
$FileSpecs = ForEach-Object{$($Path + "\*.flac"), $($Path + "\*.dsf")}

Get-ChildItem -Path $FileSpecs

# In case you want to use a single line of commands:
'C:\Xpto\123' | ForEach-Object{$($_ + "\*.flac"), $($_ + "\*.dsf")} | Get-ChildItem

You must log in to answer this question.