我有一个 Powershell 脚本,它采用文件名作为输入。
param([string]$folder, [string]$input_filename)
$logfile=$folder + "\duplicate.log"
Write-Output "`nScript: `n$transformation_filename`nLogfile: " | Out-file $logfile -Append
这对于大多数文件名都适用,但当文件名或文件夹名称包含 [] 时,它就会崩溃。
dupfile.ps1 "C:\foldername [w]" "filename.xml"
第 3 行抛出此错误: 无法执行操作,因为通配符路径 C:foldername [w]\duplicate.log 未解析为文件。
因此必须更字面地对待变量。
$logfile='$folder' + "\duplicate.log"
不,这太字面意思了。
$logfile="$folder" + "\duplicate.log"
不,同样的错误。
如何告诉 Powershell 插入变量值,但不要尝试将该值中的任何内容解释为通配符?
编辑:我正在使用 Powershell 5。 我的 dupfile.ps1 仅包含上面的 3 行。 从 PS shell 使用此命令来运行脚本: C:_SCRIPTS_\dupfile.ps1 "C:\foldername [w]""test.txt"
如果可以的话,我还有一个补充。我有几行将错误消息重定向到日志文件。
Copy-Item -LiteralPath $inputPath -Destination $outputPath 2>&1|%{ "$_" } >>$logfile
重定向再次经过 []。我认为我不能在这里使用 -LiteralPath。
最佳答案
tl;博士
确保重定向操作中的文件路径参数 $var
得到处理 > $var
/>> $var
字面上如果它包含[
和]
,请使用
|输出文件 -LiteralPath $var
/|改为 Out-File -LiteralPath $var -Append
。
Copy-Item -LiteralPath $inputPath -Destination $outputPath 2>&1 |
ForEach-Object { "$_" } |
Out-File -LiteralPath $logfile # literal alternative to >> $logfile
就您的情况而言,您可能必须将其与 redirection 结合使用。为了确保除了成功之外还有其他流 output stream目标:
# Literal equivalent of *>> $logfile
... *>&1 | Out-File -LiteralPath $logfile -Append
不幸的是,仅捕获给定的其他流会变得很棘手,因为您需要使用适当的-*Variable
通用参数,例如common -ErrorVariable
parameter :
# Literal equivalent of 2>> $logfile
... -ErrorVariable errs
$errs | Out-File -LiteralPath $logfile -Append
警告:
尝试通过转义文字路径来绕过上述解决方案是很诱人的,这样当它被解释为通配符时,就会按字面意思处理,使用
[WildcardPattern]::Escape()
.但是,从 PowerShell 7.2.6 开始,这无法按预期工作,因为文字路径的转义形式随后将用作文字文件路径 - 请参阅 GitHub issue #9475以及关于
>
/>>
, ... 是否应该将其参数视为通配符的讨论。
# !! Arguably SHOULD work, but doesn't as of 7.2.6:
# The file that is created is LITERALLY named for the ESCAPED form:
# `[1`].txt
'hi' > ([WildcardPattern]::Escape('[1].txt'))
背景信息:
PowerShell provider 的 -Path
(-FilePath
) 参数 cmdlet 需要 wildcard expressions用于通过名称或路径模式定位文件系统项。此参数隐式由第一个位置参数定位,即,如果您没有显式命名目标参数 - 例如,Get-ChildItem foo
与 Get-ChildItem -Path foo 隐式相同。
令人惊讶的是,这不仅仅适用于文件读取 cmdlet(例如
Get-ChildItem
、Get-Content
),还可以用于文件写入 cmdlet(例如,Set-Content
、Out-File
)。- 请注意,由于历史原因,名为
-Path
的参数在Out-File
中被称为-FilePath
。在PowerShell(核心)7+ 中,为了保持一致性,-Path
被引入作为别名。
- 请注意,由于历史原因,名为
可以说,在文件编写/创建 cmdlet 中,这种行为不合适 - 考虑到您通常确切地知道什么您想要定位的 >literal 路径 - 有几个 GitHub 问题讨论了这个问题;所有相关讨论的概述可以在 this comment on GitHub issue #17106 中找到。 .
为了按照字面意义(逐字)处理此类参数,您必须
改用-LiteralPath
参数。
实际上,> $var
和 >> $var
是 | 的别名。 Out-File -FilePath $var
和 | Out-File -FilePath $var -Append
,这意味着 $var
被解释为通配符。
使用带有 -LiteralPath
的显式 Out-File
调用(如顶部所示)可以避免此问题。
关于powershell - 忽略 Powershell 字符串中的通配符 [],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73331921/