我运行这个命令:
Get-ChildItem -recurse -file | ForEach-Object { (Get-Content $_).Replace('hi there','hello') | Set-Content $_ }
并收到此错误:
InvalidOperation: You cannot call a method on a null-valued expression.
InvalidOperation: You cannot call a method on a null-valued expression.
你知道这是为什么吗?
正如 Santiago Squarzon 所指出的 - 也许令人惊讶 - 使用
Get-Content
读取 空 文件(0
字节)输出 $null
(无论您是否也使用 -Raw
)。[1]
在 $null
上调用
any方法会导致您看到的错误。
一个简单的解决方案是过滤掉空文件,无论如何对它们执行任何替换都是没有意义的:
Get-ChildItem -Recurse -File |
Where-Object Length -gt 0 |
ForEach-Object {
($_ | Get-Content -Raw).Replace('hi there','hello') |
Set-Content -NoNewLine -LiteralPath $_.FullName
}
请注意以下额外改进:
$_ | Get-Content
相当于 Get-Content -LiteralPath $_.FullName
,并确保每个输入文件都按其完整路径传递,并且按字面意义(逐字)解释该路径。
-Raw
确保文件内容被读取作为单个(多行)字符串,从而加快替换速度。
-NoNewLine
防止
Set-Content
将额外的换行符附加到(可能已修改的)文件内容。
[1] 从技术上讲,使用 -Raw
的 not
会发出“可枚举 null”,这是特殊的
[System.Management.Automation.Internal.AutomationNull]::Value
单例,表示命令缺少输出。但是,在表达式 的上下文中,例如方法调用,该值的处理方式与
$null
相同 - 请参阅此答案 了解更多信息。
-Raw
,您可能会认为应该返回空字符串 而不是
$null
,如GitHub 问题 #3911 中所建议。