首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PowerShell标准误差输出中的随机换行

PowerShell标准误差输出中的随机换行
EN

Stack Overflow用户
提问于 2018-09-21 08:58:38
回答 3查看 961关注 0票数 5

我想用.iso将许多.mp4文件转换为HandBrake,所以我尝试使用命令行接口。我更喜欢用powershell来编写脚本,而不是批处理文件。但是,如果我使用powershell,标准错误将包含任意位置的换行。

为了排除故障,我在powershell和批处理中创建了一个简化脚本。

Powershell:

代码语言:javascript
复制
& "$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"

批处理文件:

代码语言:javascript
复制
"%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:

代码语言:javascript
复制
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

批处理文件:

代码语言:javascript
复制
[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获得标准的错误输出?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-10-08 01:01:28

您可以使用Start-Process命令,使用-RedirectStandardError

-RedirectStandardInput-Wait选项。

与大多数shells一样,这些-Redirect...选项在Start-Process上可以直接重定向到目标文件。据我所知,这不是PowerShell角括号重定向的工作方式,而是尖括号通过另一个PowerShell管道输送输出,使用Write-File (或其他什么),它在接收到的字符串之间插入换行。

我不清楚这件事的确切细节,但我很高兴听到它似乎像对我一样为你解决了这个问题。

票数 1
EN

Stack Overflow用户

发布于 2018-10-08 15:43:02

我认为这里的问题是控制台有一定的宽度,控制台本身本质上是被重定向到文件的。

我的解决方案是将输出直接重定向到管道,使用:

代码语言:javascript
复制
2>&1 #Interpreted by the console
2>&1 | x #Output directly to x

然后使用Out-File和可用的-Width参数:

代码语言:javascript
复制
$(throw thisisnotsometthingyoucanthrowbutisinfactaverylongmessagethatdemonstratesmypoint) 2>&1 |
 Out-File "test.txt" -Width 10000

在本例中,powershell将在包装文本之前编写10,000个字符。

然而,你也有一些奇怪的行距,我现在不能复制。尽管如此,现在您已经知道了如何通过管道发送输出,您可以使用其他方法来删除换行。

例如,可以使用this function打印导致换行的精确控制字符。

代码语言:javascript
复制
$(throw error) 2>&1 | Out-String | Debug-String

然后,您可以查看输出并替换问题字符,如下所示:

代码语言:javascript
复制
$(throw error) 2>&1 | Out-String | % {$_ -replace "`r"} | Out-File "test.txt" -Width 10000
票数 1
EN

Stack Overflow用户

发布于 2018-10-14 19:57:26

Burt Harris' helpful answer通过Start-Process向您展示了避免问题的一种方法,这要求您从根本上不同地构造命令。

如果等效批处理文件产生的输出足够,那么有一种更简单的方法:简单地调用cmd /c cmd 并让cmd处理输出重定向,就像在批处理文件中那样:

代码语言:javascript
复制
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解释的。

还请注意可执行路径周围嵌入的转义双引号(`"),以确保cmd.exe将整个路径视为一个单一的、双引号字符串。

至于您所看到的额外的换行:我没有具体的解释,但我可以告诉您> 2> 在PowerShell中的工作方式是如何不同的--与cmd.exe (批处理文件)和Start-Process ( -RedirectStandard* )相比

  • cmd.exe的重定向操作符(>)将原始字节写入指定的目标文件,无论是重定向stdout (仅重定向>或显式地重定向1>)还是重定向stderr (2>);因此,外部程序(如HandBrakeCLI.exe )输出的文本将按原样传递。
  • Start-Process在引擎盖下使用.NET API,在指定-RedirectStandardOutput和/或-RedirectStandardError参数时基本上是这样做的。

相比之下,Powershell自己的>操作符的功能不同:

  • PowerShell -在内部(当调用本机PowerShell命令时),它使用PowerShell的富输出格式系统将输入对象(不是字符串)转换为字符串,然后使用下面详述的字符编码将它们发送到输出文件。
  • 输出从外部程序接收到的假定为 text,默认情况下其编码被假定为系统的OEM字符编码,如[console]::OutputEncodingchcp所示。解码文本逐行加载到.NET字符串(本质上是基于UTF-16的字符串)。
代码语言:javascript
复制
- For **redirected** _**stdout**_ **output**, these strings are _**re-encoded**_ **on output to the target file**, using the following encoding by default:
代码语言:javascript
复制
    - Windows PowerShell: UTF-16LE ("Unicode")
    - PowerShell Core: UTF-8 _without BOM_
    - Note: Only in Windows PowerShell v5.1 or higher and PowerShell Core can you change these defaults - see [this answer](https://stackoverflow.com/a/42451413/45375) for details.

代码语言:javascript
复制
- By contrast, **when redirecting** _**stderr**_ **output**, via stream `2` (PowerShell's error stream), the strings are _wrapped in error objects_ (instances of type `[System.Management.Automation.ErrorRecord]`) before being output, and the resulting objects are converted to strings based on PowerShell's output-formatting system, and the same character encoding as above is applied on output to the target file.
代码语言:javascript
复制
    - You can see evidence of that in your output containing extra information and lines such as `HandBrakeCLI.exe : [10:41:44] hb_init: starting libhb thread` and  `At C:\Test\phandbrake.ps1:1 char:2`, ...
    - It also means that extra line breaks can be introduced, because text produced by the output-formatting system assumes a fixed line width based on the console window's width.
    - That said, that doesn't explain the oddly placed line breaks in your case.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52440154

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档