我有一个同时包含.xls,.xlsx和.xlsm文件的文件夹,并且只想过滤.xls文件。
为什么以下行无法正常运行?我看到了.xls,.xlsx和.xlsm结果。
Get-ChildItem $(Get-Location) -Filter *.xls | ForEach-Object { $_.Extension }
答案 0 :(得分:1)
-Filter
参数的通配符匹配不是由PowerShell执行的,而是由执行的,它会传递给文件系统提供程序,最后传递给Windows API。
在该处执行的匹配会产生许多遗留的行为和怪癖,包括您看到的那些:
在 Windows PowerShell 中, -Filter *.xls
的行为类似于-Filter *.xls*
。因此,例如-Filter *.xls
与foo.xls
和foo.xlsx
都匹配;之所以会这样,是因为 8.3(短)文件名也被 在幕后匹配;例如,foo.xlsx
的8.3文件名看起来像FOO~1.XLS
;注意.xlsx
到.XLS
的截断(和大写)。
虽然短名称匹配行为在PowerShell [Core] v6 + 中不再发生,但幸运的是,其他遗留的古怪现象仍然存在 [1] < / sup>,以及最明显的区别(不会消失):仅 PowerShell 通配符表达式(请参见about_Wildcards
)支持字符通过[...]
(例如[a-z]
)进行设置/设置--Filter
不支持它们。
与-Filter
/ -Path
(参见下文)相比,通常更优选使用-Include
参数(由于其优越性)性能(过滤是在源头进行 ,而不是在PowerShell中进行)。
解决方法是使用-Path
参数,以便使用 PowerShell的通配符匹配:
Get-ChildItem -Path (Join-Path (Get-Location) *.xls) | ForEach-Object { $_.Extension }
# Or, more simply
Get-ChildItem -Path $PWD/*.xls | ForEach-Object Extension
注意:在-Recurse
中,您将使用-Include
参数。
[1]值得注意的其他怪癖:
多个连续的?
通配符可以匹配更少个字符的名称。
Get-ChildItem -Filter ??.txt
匹配aa.txt
,并且意外地匹配a.txt
模式*.
与无扩展名的文件和目录名称匹配。
例如,Get-ChildItem -File -Filter *.
查找名称不带扩展名的所有文件(-File
)(例如file
);这个怪癖实际上是有用的,因为它是查找无扩展名文件的最简单且性能最佳的方式(-Path *.
不能 起作用,因为它会查找文件名字面意思以.
结尾)。
注意:在PowerShell Core 6.x(从6.2.3版本开始)中,这是临时更改,但是从PowerShell Core 7.0开始,行为已恢复。
> li>相反,*.*
也包括无扩展名的文件和目录名称。
有关背景故事和血腥细节,请参见this excellent answer的Zenexer。
答案 1 :(得分:0)
-filter与文件名的简短版本匹配。这已经在其他地方讨论过了。在Powershell 6中已解决。
echo hi > file.xlsx
dir -filter *.xls
Directory: C:\users\js\foo
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/11/2020 9:54 AM 4 file.xlsx
cmd /c dir /x
Volume in drive C is DISK
Volume Serial Number is A11A-AA11
Directory of C:\users\js\foo
02/11/2020 09:54 AM <DIR> .
02/11/2020 09:54 AM <DIR> ..
02/11/2020 09:54 AM 4 FILE~1.XLS file.xlsx
1 File(s) 4 bytes
2 Dir(s) 3,380,170,752 bytes free