我想使用HandBrake将许多.iso文件转换为.mp4,因此我尝试使用命令行界面。我宁愿在Powershell中而不是批处理文件中为此编写脚本。但是,如果我使用powershell,标准错误将在随机位置包含换行符。
为了进行故障排除,我同时在Powershell和批处理中创建了一个简化的脚本。
Powershell:
& "$Env:ProgramFiles\HandBrake\HandBrakeCLI.exe" @(
'--input', 'V:\',
'--title', '1', '--chapter', '1',
'--start-at', 'duration:110', '--stop-at', 'duration:15',
'--output', 'pmovie.mp4',
'--format', 'av_mp4'
) > ".\pstd.txt" 2> ".\perr.txt"
批处理文件:
"%ProgramFiles%\HandBrake\HandBrakeCLI.exe" --input V:\ --title 1 --chapter 1 --start-at duration:110 --stop-at duration:15 --output ".\cmovie.mp4" --format av_mp4 > ".\cstd.txt" 2> ".\cerr.txt"
两个脚本都创建相同的.mp4文件,不同之处仅在于它们创建的标准错误输出:
Powershell:
HandBrakeCLI.exe : [10:41:44] hb_init: starting libhb thread
At C:\Test\phandbrake.ps1:1 char:2
+ & <<<< "$Env:ProgramFiles\HandBrake\HandBrakeCLI.exe" @(
+ CategoryInfo : NotSpecified: ([10:41:44] hb_i...ng libhb thread
:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
[10:41:44] thread 541fc20 started ("libhb")
HandBrake 1.1.2 (2018090500) - MinGW x86_64 - https://handbrake.fr
8 CPUs detected
O
pening V:\...
[10:41:44] CPU: Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz
[10:41:44] - Intel microarchitecture Sandy Bridge
[10:41:44] - logical processor count: 8
[10:41:44] Intel Quick Sync Video support: no
[10:41:44] hb_scan: path=V:\, title_index=1
src/libbluray/disc/disc.c:424: error opening file BDMV\index.bdmv
src/libbluray/disc/disc.c:424: error opening file BDMV\BACKUP\index.bdmv
[10:41:44] bd: not a bd - trying as a stream/file instead
libdvdnav: Using dvdnav version 6.0.0
l
ibdvdnav: Unable to open device file V:\.
libdvdnav: vm: dvd_read_name failed
libdvdnav: DVD disk re
ports i
tself wi
th Region mask 0x
0000000
0. Reg
ions:
1 2 3 4 5
6 7 8
批处理文件:
[10:41:35] hb_init: starting libhb thread
[10:41:35] thread 5a2cc30 started ("libhb")
HandBrake 1.1.2 (2018090500) - MinGW x86_64 - https://handbrake.fr
8 CPUs detected
Opening V:\...
[10:41:35] CPU: Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz
[10:41:35] - Intel microarchitecture Sandy Bridge
[10:41:35] - logical processor count: 8
[10:41:35] Intel Quick Sync Video support: no
[10:41:35] hb_scan: path=V:\, title_index=1
src/libbluray/disc/disc.c:424: error opening file BDMV\index.bdmv
src/libbluray/disc/disc.c:424: error opening file BDMV\BACKUP\index.bdmv
[10:41:35] bd: not a bd - trying as a stream/file instead
libdvdnav: Using dvdnav version 6.0.0
libdvdnav: Unable to open device file V:\.
libdvdnav: vm: dvd_read_name failed
libdvdnav: DVD disk reports itself with Region mask 0x00000000. Regions: 1 2 3 4 5 6 7 8
libdvdread: Attempting to retrieve all CSS keys
libdvdread: This can take a _long_ time, please be patient
libdvdread: Get key for /VIDEO_TS/VIDEO_TS.VOB at 0x00000130
libdvdread: Elapsed time 0
这让我感到困扰,因为我想检查这些文本文件以确保编码过程中没有错误。
我想这可能与写入同一流的线程之间缺乏同步有关,但是我不确定。
问题:如何在没有这些随机换行符的情况下从PowerShell获取标准错误输出?
答案 0 :(得分:1)
您可以尝试使用Start-Process
,
-RedirectStandardError
和-RedirectStandardInput
选项的-Wait
命令。
-Redirect...
上的这些Start-Process
选项可以像大多数Shell一样直接将OS级I / O重定向到目标文件。据我了解,这不是PowerShell尖括号重定向的工作方式,而是尖括号使用Write-File
(或其他方式)将输出通过另一个PowerShell管道传递给另一个PowerShell管道,该管道将在接收的字符串之间插入换行符。
我不确定确切的细节,但我很高兴听到它似乎可以像我一样为您解决问题。
答案 1 :(得分:0)
我认为这里的问题是控制台有一定的宽度,并且控制台本身实际上已被重定向到文件。
我对此的解决方案是使用以下命令将输出直接重定向到管道:
2>&1 #Interpreted by the console
2>&1 | x #Output directly to x
然后将Out-File
与可用的-Width
参数一起使用:
$(throw thisisnotsometthingyoucanthrowbutisinfactaverylongmessagethatdemonstratesmypoint) 2>&1 |
Out-File "test.txt" -Width 10000
在这种情况下,powershell在换行之前将写入10,000个字符。
但是,您那里也有一些奇怪的换行符,我现在无法复制。就是说,既然您知道如何通过管道发送输出,则可以使用其他方法来删除换行符。
例如,您可以使用this function来打印出导致换行的确切控制字符。
$(throw error) 2>&1 | Out-String | Debug-String
然后,您可以遍历输出并替换问题字符,如下所示:
$(throw error) 2>&1 | Out-String | % {$_ -replace "`r"} | Out-File "test.txt" -Width 10000
答案 2 :(得分:0)
Burt Harris' helpful answer通过Start-Process
向您展示了一种避免问题的方法,该方法要求您从根本上对命令进行结构化。
如果等效的批处理文件产生的输出足够,则有一种更简单的方法:像批处理一样,只需调用cmd /c
并让cmd
处理输出重定向文件:
cmd /c "`"`"$Env:ProgramFiles\HandBrake\HandBrakeCLI.exe`"`"" @(
'--input', 'V:\',
'--title', '1', '--chapter', '1',
'--start-at', 'duration:110', '--stop-at', 'duration:15',
'--output', 'pmovie.mp4',
'--format', 'av_mp4'
) '> .\pstd.txt 2> .\perr.txt'
请注意如何将两个输出重定向作为单个带引号的字符串传递,以确保它们由cmd.exe
而不是PowerShell解释。 / p>
还请注意,在可执行路径周围嵌入转义的双引号(`"
),以确保cmd.exe
将整个路径视为一个单引号引起来的字符串。
关于您看到的额外的换行符:
我没有具体的解释,但可以告诉您 >
和2>
在PowerShell中的工作方式是什么-与cmd.exe
(批处理文件)和{{ 1}}和Start-Process
:
-RedirectStandard*
的重定向操作符(cmd.exe
)在重定向标准输出(仅>
或显式{{1}时)将原始字节写入指定的目标文件。 })和stderr(>
);这样,外部程序(例如1>
)输出的文本将原样传递。
2>
在后台使用.NET API,当指定HandBrakeCLI.exe
和/或Start-Process
参数时,其作用基本相同。
相比之下,Powershell自己的-RedirectStandardOutput
运算符的功能有所不同:
PowerShell- 内部(在调用本地PowerShell命令时)将输入的对象(还没有字符串)转换为字符串使用PowerShell的丰富输出格式系统,然后使用下面详述的字符编码将它们发送到输出文件。
从外部程序收到的 输出假定为 text ,其编码被假定为系统的OEM字符编码,默认值,如-RedirectStandardError
和>
中所反映。 解码后的文本会逐行加载到.NET字符串(本质上是基于UTF-16的字符串)中。
对于重定向的 stdout 输出,这些字符串在输出到目标文件时被 重新编码 >,默认情况下使用以下编码:
相反,通过流[console]::OutputEncoding
(PowerShell的错误流)重定向 stderr 输出时,字符串被错误包装对象(类型为chcp
的实例),然后根据PowerShell的输出格式系统将生成的对象转换为字符串,并将与上述相同的字符编码应用于输出到目标文件
2
和
[System.Management.Automation.ErrorRecord]
,...