本来以为 Selet-Object 应该能发挥作用,但看过帮助文档之后发现对于筛选来说它只能执行比较简单的操作(First, Last, Unique, Skip, and Index)。
目前我的方法是用%
,获取文件列表之后,根据后缀属性用if
判断,然后再直接返回。
$FileList = $Dir | Get-ChildItem -Recurse -File
$PyFileList = $FileList | ForEach-Object { if ($_.Extension -eq '.py') { $_ } }
这种办法目前用起来也还可以,但感觉用if(){}
,总是不 PowerShellic 。
那么针对这种需求的最佳实践是什么?
高度怀疑应该是有更好的方式的,如果没有的话自己写个 Cmdlet,倒是不错,直接传递脚本块儿就根据布尔值返回对象,从而免去各种括号。这个需求是高频的。
1
Yadomin 2021-05-01 10:08:30 +08:00 1
难道不是 Get-Item *.md 吗
|
2
Yadomin 2021-05-01 10:09:05 +08:00
Get-ChildItem (
|
3
chinvo 2021-05-01 10:10:01 +08:00 via iPhone 1
-Filter
|
5
h404bi 2021-05-01 10:16:42 +08:00 1
|
6
AndyAO OP 找到了,应该用 Where-Object,这也是个很常用的 Cmdlet,别名是?
|
7
AndyAO OP ⚠⚠⚠
人们经常会将 Select-Object 和 Where-Object 这两个 PowerShell 命令搞混,虽然目前你还没有见过 Where-Object 。 Select-Object 用于选择所需的属性(或列),还可以选择输出行的任意子集(使用 -First 和 -Last )。 Where-object 基于筛选条件从管道中移除或过滤对象。 |
9
AndyAO OP @h404bi #5 又例如,根据文件内容是否包含某字符串,目前感觉 Where-Object 是最佳实践
```PowerShell $PyFileList | Where-Object {($_ | Get-Content -Raw).Contains('Unit.')} ``` |
10
AndyAO OP |
11
h404bi 2021-05-01 10:42:48 +08:00
@AndyAO #8 组合条件过滤确实得用上 Where-Object 。不过就标题的问题来说,用通配符是最 PowerShell 的写法,官方文档给的 examples 。
如果用过 Where-Object 的 alias ( ? ),应该就很容易记住管道过滤时用它了。:D |
12
zgzb 2021-05-01 11:52:40 +08:00 1
foreach($Dir in dir *.md,*.txt,*.html)
|
13
geelaw 2021-05-01 12:21:06 +08:00 2
Select-Object 主要功能是 map,比如从具有 A B C 三个属性的对象中获得具有 A B 两个属性的对象,而不是根据属性留下或去掉对象。
注意用 Where-Object 或者 ForEach-Object 或者 ForEach 循环筛选文件和直接用通配符是不同的,取决于具体写法,因为 string 对象的方法默认是大小写敏感、当前文化,而 Get-ChildItem 的 globbing 是大小写不敏感(我不清楚它比较的文化是什么)。 例如 Get-ChildItem | Where-Object { $_.EndsWith('.ps1') } 无法得到扩展名是 .Ps1 或者 .PS1 或者 .pS1 的文件。 另外“扩展名”的定义也比较模糊,我想你的意思应该是指“长扩展名”,即不考虑短文件名的情况(例如 a.theme 的短文件名是 a.the ,因此 .the 是 a.theme 的短扩展名)。好消息是:PowerShell 默认情况下不会用通配符匹配短文件名。 |
15
imn1 2021-05-01 12:58:34 +08:00
powershell 如果想快、高效,尽可能用.net 框架下的命令,ps 原生的命令当然比较 PowerShellic,但做大量时工作有点慢
|
16
AndyAO OP 1. 在 PowerShell 中 glob 和通配符应该是同义词[^1],-like 的行为就是所有通配符参数的标准行为
2. -eq 对于字符串的比较也是忽略大小写的,这个和 C#上的默认行为是完全不同的 [^1]:Using wildcard characters is sometimes referred to as globbing. from: https://docs.microsoft.com/en-us/powershell/scripting/developer/cmdlet/supporting-wildcard-characters-in-cmdlet-parameters?view=powershell-7.1 @imn1 #15 的确是这样的,本来 PowerShell 的实现好像就不怎么高效吧,而且为了交互式运行方便,会添加很多的额外属性,而且会默认产生很多的展示用信息,所以速度慢很多很多。 对于很轻的任务来说,编写效率要远远重于运行效率,PowerShellic 是很值得的;如果有执行大量运算的任务,确实应该用.Net Native 来加速,这就有点类似于 Ruby 和 Python 之于 C 。 |