PowerShell中的Test-Path行为

5

我正在尝试使用PowerShell编写脚本批量转换视频文件。

我打算这样使用它:进入一个充满视频文件的文件夹并运行脚本。它使用一个可以在“命令行模式”下运行的转换程序(名为Handbrake),并在文件扩展名之前保存已转换的文件,并附加“-android”。例如,如果我有一个名为video1.avi的文件,运行脚本后文件夹中有两个文件:video1.avi和video1-android.avi。

我之所以想这样做,是为了检查每个视频文件是否存在其转换版本(名称附加了-android)。如果存在,则跳过该文件的转换。

这就是我的问题所在。问题出在Test-Path的行为上(我用它来测试文件是否存在)。

问题在于,如果视频文件有一个“不寻常”的名称(例如,在我的情况下是video[long].avi),则无论如何都会返回False。

你可以很容易地测试这一点:

进入一个空文件夹, 运行记事本创建一个带有“ [ ”的文件:

&notepad test[x].txt

保存文件

然后执行以下步骤:

Get-ChildItem | ForEach-Object {Test-Path $_.FullName}

它没有返回true!它应该返回true吗?如果文件名中有“ [”(我没有检查其他特殊字符),那么它不会返回true。

我意识到,如果你转义“ [”和“]”,它就可以正常工作。

Test-Path 'test`[x`].txt'

返回true。

我该如何避免这个问题?我想要做到:给定一个文件的BaseName,将其附加为“-android.avi”,并检查是否存在具有该名称的文件。

谢谢, 瑞

2个回答

9
许多PowerShell cmdlet具有支持通配符的路径参数。 正如您所观察到的那样,在PowerShell中,不仅*是通配符,而且[]也被视为通配符字符。 您可以在about_Wildcards帮助主题中阅读更多相关信息。
对于您的问题,如果您不需要使用通配符,则建议使用-LiteralPath参数。 该参数不支持通配符,并接受[]作为文字路径字符,例如:
Get-ChildItem | ForEach {Test-Path -LiteralPath `
                         "$([io.path]::ChangeExtension($_.FullName,'avi'))"}

FYI,将Get-ChildItem的输出直接传输到Test-Path的原因是LiteralPath参数有一个别名"PSPath",该别名映射到由Get-ChildItem输出的FileInfo对象上的PSPath属性。该属性通过“属性名称”绑定到LiteralPath(er PSPath)参数。

1
 dir | % {test-path "$($_.Name)-android.avi"}

1
你能详细解释一下吗,为什么要用$($_.Name)和"%{ }"? - Rui
1
%ForeachForeach-Object命令的别名。在字符串内,您可以进行简单的变量扩展,例如"$_",但如果要评估表达式(例如访问对象的属性),则需要使用子表达式,例如 "$($_.Name)" - Keith Hill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接