表达式或语句中出现意外的标记“ -UFormat”

时间:2018-12-03 15:09:52

标签: powershell

我想获取列表

  • 文件/文件夹的全路径名
  • 文件/文件夹的最后写入时间
  • 文件/文件夹的大小

基于最终用户想要的3条信息中的哪条。 我希望扩展我的此功能,以根据提供的输入来容纳更多属性。下面给出的是我的代码片段及其后面的错误。

  • $Path是路径,它是输入
  • $CustomMetaList是一个属性数组,它是一个输入。
    $BaseCmd = "Get-ChildItem $Path -Recurse"
    $Hidden = ""
    $FullName = ""
    $LastWriteTime = ""
    $Size = ""
    $PropList = ""
    $CustomMetaList = $CustomMetaList.split(",")
    foreach ($Meta in $CustomMetaList) {
        if ($Meta -eq "'Hidden'") {
            $Hidden = "-Force"
        }
        if ($Meta -eq "'FullName'") {
            $PropList = [String]::Join(",","@{e={`$_.FullName};width=250}")
        }
        if ($Meta -eq "'LastWriteTimeUtc'") {
            $PropList = [String]::Join(",",$PropList,"@{e={`$_.LastWriteTimeUtc -UFormat %s}}")
        }
        if ($Meta -eq "'Size'") {
            $PropList = [String]::Join(",",$PropList,"@{e={`$_.Length}}")
        }
    }
    Invoke-Expression "$BaseCmd $Hidden | Format-Table -HideTableHeaders -Property $PropList -AutoSize | Out-String -Width 5000"
}

当我尝试运行脚本时收到以下错误, 您对出什么问题有任何想法吗?

Invoke-Expression :
At line:1 char:210
+ ... stWriteTimeUtc -UFormat %s}},@{e={$_.Length}} -AutoSize | Out-String -Width 5000
+                    ~~~~~~~~
Unexpected token '-UFormat' in expression or statement.
At line:1 char:219
+ ... meUtc -UFormat %s}},@{e={$_.Length}} -AutoSize | Out-String -Width 5000
+                    ~~
Unexpected token '%s' in expression or statement.
At E:\299955427760_GetData.ps1:114 char:5
+           Invoke-Expression "$BaseCmd $Hidden | Format-Table -HideTableHeaders -Proper ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ParserError: (:) [Invoke-Expression], ParseException
    + FullyQualifiedErrorId : UnexpectedToken,Microsoft.PowerShell.Commands.InvokeExpressionCommand

1 个答案:

答案 0 :(得分:4)

Ansgar Wiechers忠实地建议,Invoke-Expression should be avoided,因为几乎总是有更好的解决方案,并且存在安全风险。

通常,对于迭代构造具有不同参数的命令,参数splatting是最佳解决方案,尽管在​​您的情况下这不是绝对必要的-请参阅底部。

但是,您的问题与Invoke-Expression 的使用无关,因为它是由以下表达式引起的:

$_.LastWriteTimeUtc -UFormat %s  # !! Syntax error

您只能将-UFormat传递给Get-Date cmdlet,而不能传递给变量或表达式:

Get-Date -Date $_.LastWriteTimeUtc -UFormat %s  # OK

此外,由于Windows PowerShell v.5.1中的错误(自从在PowerShell Core 中得到纠正),Get-Date -UFormat %s也会输出 fractional 秒,这是不正确的;您可以通过强制转换为[int]来解决此问题:

[int] (Get-Date -Date $_.LastWriteTimeUtc -UFormat %s)

(考虑到Get-Date -UFormat总是输出 strings ,即使没有错误,您可能也想这样做以接收数字结果。)< / p>

顺便说一句:另一个错误导致默认情况下结果基于 local 时间,而Unix时间戳要求基于 UTC ;由于您使用的是属性.LastWriteTimeUtc,因此您的代码不会受到影响。


这是一种避免使用Invoke-Expression并且也更短的解决方案:

# Sample input values.
$Path = $env:TEMP
$CustomMetaList = 'FullName,Size,LastWriteTimeUtc'

# Construct the array of property definitions to pass to Select-Object
# based on the custom list, and record in $force whether hidden items 
# should be included.
$props = switch ($CustomMetaList -split ',') {
    'Hidden' { $force = $True; continue } # save in Boolean var.
    'FullName' { $_; continue }           # same name as property
    'Size' { 'Length'; continue }         # map 'Size' to 'Length'
    'LastWriteTimeUtc' {                  # calculated property
      @{ n=$_; e = { [int] (Get-Date -Date $_.LastWriteTimeUtc -UFormat %s) } }
    }
}


Get-ChildItem $Path -Recurse -Force:$force | 
  Format-Table -Property $props -HideTableHeaders -AutoSize |
    Out-String -Width 5000

请注意如何使用switch隐式迭代$CustomMetaList -split ','返回的数组元素。 switch语句的分支处理程序默认情况下都经过 all 测试,因此一旦找到匹配项,就使用continue来使其短路。注意:不要使用break,因为它会停止遍历其他数组元素。

switch语句迭代的输出隐式收集在存储在$props中的 array 中,该数组随后传递给Format-Table

-Force:$force是一种模拟传递/不传递开关参数-Force的效果的方法:如果$force$true,则与{{ 1}}已通过;否则,将视为未通过-Force

这将产生如下内容:

-Force