我有一个powershell脚本,包含三个部分:1。修改文件名以删除MicrosoftOS保留字符;2.运行/usr/bin/flac将*.wav文件转换为*.flac,3。使用.dll将ID3标记从*.mp3文件复制到*.flac文件。
这个脚本的所有三个部分都在我以前的Kubuntu v222.10系统上运行。在MXLinux v21上,此脚本在步骤2失败。错误是";找不到文件";对于/usr/bin/flac命令的对象/usr/bin/flac加载,但表示找不到指定给它的文件。步骤1和3有效(我知道这一点,因为脚本需要一个参数来跳过步骤2;因此,如果*.wav文件已经是*.flac文件,我可以运行它,例如,在上一次运行中,步骤2成功,但由于某种原因,步骤3失败)。
这是PS代码片段:
[string] $flacEXE = '/usr/bin/flac'
if($convert -eq "yes" || $convert -eq "Yes" || $convert -eq "YES")
{
if (Test-Path -Path "$workingPath/*cr.wav")
{
$CRFiles = Get-ChildItem -Path "$workingPath/*cr.wav"
foreach ($crFile in $CRFiles)
{
$output = & $flacEXE "`"$crFile`""
if ($LASTEXITCODE -ne 0)
{
Write-Host "The flac conversion created an error..." -ForegroundColor Red
Write-Host "$output" -ForegroundColor Red
}
}
}
else
{
Write-Host "No ClickRepair files found but Convert was Yes ... Aborting script.`n" -ForegroundColor Red
throw $_.Exception.Message
exit
}
}
如果我在powershell中的提示符下运行/usr/bin/flac(例如,在Visual Studio代码中),它将失败。如果我从linux终端在同一文件夹中的同一文件上运行/usr/bin/flac,它就可以工作了。
我认为这一定是某种权限问题(范围问题?),但无法解决。这些文件位于/mnt/上安装的NTFS USB卷上。我最近迁移到MXLinux,因此重新创建了我的系统。这是我第一次使用这个powershell脚本。
我应该注意的是,Set ExecutionPolicy的一致性在Linux上对Powershell Core无效,只在Windows系统上有效,所以这没有用。
替换:
$output = & $flacEXE "`"$crFile`""
带有:
$output = & $flacEXE $crFile
与POSIX兼容shell(如
bash
)不同,您不需要而在PowerShell中的"..."
中包含作为参数传递的变量引用-PowerShell没有与POSIX兼容性shell的所谓shell扩展等效的功能,尤其是没有分词;因此,带有空格的值不需要在PowerShell中使用"..."
进行保护。"`"$crFile`""
之所以有效,只是因为PowerShell如何将嵌入双引号的参数传递给外部程序(直到PowerShell 7.2.x)的长期错误。在PowerShell 7.3.0中,此错误已修复,因此上面的内容现在(正确地)将内部
"
作为参数的逐字部分传递给目标程序。(然而,"$crFile"
在7.2.x及更高版本中都可以工作,尽管"
仍然是不必要的,如上所述)。请参阅此答案以获取更多信息,包括如何为了向后兼容性而选择旧的、已损坏的行为。还要注意的是,当前的计划是继续默认仅在类Unix平台上为新的、正确的行为,并且在Windows7.3.1之后的某个版本上的可能会默认恢复到旧的、坏的行为,新的、错误的行为需要选择加入。
顺便说一句,关于if($convert -eq "yes" || $convert -eq "Yes" || $convert -eq "YES")
:
将
if($convert -eq "yes" || $convert -eq "Yes" || $convert -eq "YES")
替换为if ($convert -eq 'yes')
-默认情况下,PowerShell不区分大小写[1]如果必须使用多个操作,则需要将它们与-or
链接,而不是与||
-||
操作命令的成功状态,而不是操作值;例如:$true || 'never get here'
和$false || 'never get here'
不会触发||
的RHS,因为$true
和$false
都是成功执行、的表达式,而不管它们的值如何,因此不会触发||
管道链运算符的RHS(类似于&&
)。对于基于值的操作(表达式返回值出),我们使用
-or
、逻辑-or
和-and
运算符。
[1]对于区分大小写的行为,使用前缀为c
的操作数变体,如-eq
;例如'FOO' -ceq 'foo'
是$false
。类似地,默认情况下,大多数标准cmdlet和switch
语句不区分大小写,并提供-CaseSensitive
开关作为opt-in