【问题标题】:Powershell Select-Object: Executing native commands in calculated propertyPowershell Select-Object:在计算属性中执行本机命令
【发布时间】:2021-04-27 12:38:15
【问题描述】:

我正在尝试创建一个报告文件,其中列出了我的 Git 存储库中的所有文件,其中包含以下列:

  • 姓名
  • 尺寸
  • 上次修改时间
  • Git 提交

前3个没问题:

gci -File -Recurse | Select-Object -Property @{
 label = 'Size(KB)'
 expr = { [string]::Format("{0:0.00}", $_.Length/1KB) }
}, LastWriteTime, FullName

但是,检索 git 提交需要运行 Git,一个本机命令。

我已经尝试过,其中包括:

gci -File -Recurse | Select-Object -Property @{
 label = 'Git commit'
  expr = { Invoke-Expression "git log -1 --format:format=`"%s`" -- $($_.FullName)" }
},
@{
 label = 'Size(KB)'
 expr = { [string]::Format("{0:0.00}", $_.Length/1KB) }
}, LastWriteTime, FullName

但它只是卡住了。

有人知道怎么做吗?

附: Git 的所有标志和选项都无关紧要,我只是复制了我已经做过的。

【问题讨论】:

  • 选项--format:format="%s" 看起来不对;它应该是--format=format:"%s"。 (PowerShell 将删除",但这不应该有所作为。)因此,如果将Invoke-Expression 命令替换为以下命令,它是否有效? git log -1 --format=format:"%s" -- $_.FullName
  • 现在你已经接受的答案暗示了这一点,但让我把它拼出来:git 选项有很大的不同,因为语法上无效的git 命令只产生 stderr 输出,在计算属性的上下文中,它悄悄地丢弃,因此您最终会得到一个空的Git commit 输出列。详情见我的回答。

标签: powershell


【解决方案1】:

正如 @mklement0 在 cmets 中建议的那样,问题只是您对 --format 命令的格式设置错误,足以导致问题。

你有:

 --format:format="%s"  # won't work
 --format=format:"%s"  # works

所以要修复它,我们只需换成正确的格式,给我们这个命令和下面的输出。

gci -File | Select-Object -Property @{
 label = 'Git commit'
  expr = { Invoke-Expression "git log -1 --format=format:`"%s`" $($_.Name)" }
},
@{
 label = 'Size(KB)'
 expr = { [string]::Format("{0:0.00}", $_.Length/1KB) }
}, LastWriteTime, FullName

Git commit             Size(KB) LastWriteTime         FullName                        
----------             -------- -------------         --------                        
applied gitingore      6.07     5/11/2020 11:22:06 AM C:\git\ClientFaux\.gitignore    
cleanin up layout      1.40     10/9/2020 3:20:33 PM  C:\git\ClientFaux\ClientFaux.sln
Create LICENSE (#25)   34.98    7/13/2020 9:55:00 AM  C:\git\ClientFaux\LICENSE       
Update README.md (#27) 3.37     7/13/2020 9:55:00 AM  C:\git\ClientFaux\README.md     
                       31.13    7/13/2020 9:55:27 AM  C:\git\ClientFaux\UpgradeLog.htm

【讨论】:

    【解决方案2】:

    FoxDeploy's helpful answer 包含关键指针,但让我提供一个(更正后的)您的代码的 PowerShell 惯用重新表述

    Get-ChildItem -File -Recurse | Select-Object -Property @{
        label = 'Git commit'
        expr = { git log -1 --format=format:%s -- $_.FullName }
      },
      @{
        label = 'Size(KB)'
        expr = { '{0:0.00}' -f ($_.Length/1KB) }
      }, LastWriteTime, FullName
    

    注意:


    在计算属性中调用本机可执行文件

    通常,请注意,从 expression script block ({ ... }) 的 calculated property 调用本机可执行文件并没有根本上特别之处。 p>

    特别是,以下注意事项适用:

    • 在 PowerShell 中,来自本机可执行文件的 stdout 输出总是被转换为 text[string] 实例)。如果输出包含多行,则属性值将变为包含字符串的(常规[object[]]数组

      • 如果本机可执行文件不产生 stdout 输出,则该属性的值为“nothing”,即在大多数情况下的行为类似于所谓的“Automation Null”值 ([System.Management.Automation.Internal.AutomationNull]::Value) $null
    • 本机可执行文件的任何 stderr 输出都被悄悄地丢弃。 (类似地,expression 脚本块中的 PowerShell 命令或表达式的错误会被悄悄忽略。)

    因此,为了排除expression脚本块,通过ForEach-Object命令独立执行它(其内置别名为%),以便发现任何错误;例如:

    # Uses broken `git` syntax; note the resulting error message.
    PS> (Get-ChildItem -File)[0] | % { git log -1 --format:format=%s -- $_.FullName } 
    fatal: unrecognized argument: --format:format=%s
    

    至于你尝试了什么

    由于您的 git 命令在语法上不正确,git 仅产生 stderr 输出,然后 PowerShell 忽略,如上所述。

    因此,您的 Git commit 属性最终包含“无”,这只会在输出格式中呈现空白。

    【讨论】:

    • 很好的答案!这部分尤其是Therefore, in order to troubleshoot an expression script block, execute it stand-alone, via a ForEach-Object command (whose built-in alias is %), so as to surface any errors; e.g.:
    猜你喜欢
    • 2020-10-21
    • 2015-04-26
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 2014-11-03
    • 2017-10-31
    • 2021-01-16
    • 2012-03-21
    相关资源
    最近更新 更多