V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
AndyAO
V2EX  ›  问与答

在 PowerShell 中筛选特定扩展名(例如.md)文件的“最佳实践”是什么?

  •  
  •   AndyAO · 2021-05-01 10:00:00 +08:00 · 1624 次点击
    这是一个创建于 1336 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本来以为 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,倒是不错,直接传递脚本块儿就根据布尔值返回对象,从而免去各种括号。这个需求是高频的。

    16 条回复    2021-05-01 13:27:50 +08:00
    Yadomin
        1
    Yadomin  
       2021-05-01 10:08:30 +08:00   ❤️ 1
    难道不是 Get-Item *.md 吗
    Yadomin
        2
    Yadomin  
       2021-05-01 10:09:05 +08:00
    Get-ChildItem (
    chinvo
        3
    chinvo  
       2021-05-01 10:10:01 +08:00 via iPhone   ❤️ 1
    -Filter
    AndyAO
        4
    AndyAO  
    OP
       2021-05-01 10:12:08 +08:00
    @Yadomin #1 自信点,的确是(笑哭
    不过再复杂点的属性怎么办呢?
    h404bi
        5
    h404bi  
       2021-05-01 10:16:42 +08:00   ❤️ 1
    写得真复杂...

    Get-ChildItem -Include "*.md" -Recurse

    @AndyAO #4 不明白再复杂点的属性是什么样的需求
    AndyAO
        6
    AndyAO  
    OP
       2021-05-01 10:19:24 +08:00
    找到了,应该用 Where-Object,这也是个很常用的 Cmdlet,别名是?
    AndyAO
        7
    AndyAO  
    OP
       2021-05-01 10:22:11 +08:00
    ⚠⚠⚠
     
    人们经常会将 Select-Object 和 Where-Object 这两个 PowerShell 命令搞混,虽然目前你还没有见过 Where-Object 。 Select-Object 用于选择所需的属性(或列),还可以选择输出行的任意子集(使用 -First 和 -Last )。 Where-object 基于筛选条件从管道中移除或过滤对象。
    AndyAO
        8
    AndyAO  
    OP
       2021-05-01 10:31:03 +08:00
    @h404bi 例如,根据文件长度的范围。
    AndyAO
        9
    AndyAO  
    OP
       2021-05-01 10:32:24 +08:00
    @h404bi #5 又例如,根据文件内容是否包含某字符串,目前感觉 Where-Object 是最佳实践
    ```PowerShell
    $PyFileList | Where-Object {($_ | Get-Content -Raw).Contains('Unit.')}
    ```
    AndyAO
        10
    AndyAO  
    OP
       2021-05-01 10:37:26 +08:00
    h404bi
        11
    h404bi  
       2021-05-01 10:42:48 +08:00
    @AndyAO #8 组合条件过滤确实得用上 Where-Object 。不过就标题的问题来说,用通配符是最 PowerShell 的写法,官方文档给的 examples 。

    如果用过 Where-Object 的 alias ( ? ),应该就很容易记住管道过滤时用它了。:D
    zgzb
        12
    zgzb  
       2021-05-01 11:52:40 +08:00   ❤️ 1
    foreach($Dir in dir *.md,*.txt,*.html)
    geelaw
        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 默认情况下不会用通配符匹配短文件名。
    AndyAO
        14
    AndyAO  
    OP
       2021-05-01 12:24:26 +08:00
    @geelaw #13
    你的回复考虑的真周全!
    对于比较比较复杂的情况,会经常使用的代码,这些情况的确是要考虑的。
    imn1
        15
    imn1  
       2021-05-01 12:58:34 +08:00
    powershell 如果想快、高效,尽可能用.net 框架下的命令,ps 原生的命令当然比较 PowerShellic,但做大量时工作有点慢
    AndyAO
        16
    AndyAO  
    OP
       2021-05-01 13:27:50 +08:00
    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 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4638 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 04:03 · PVG 12:03 · LAX 20:03 · JFK 23:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.