PowerShell '调用'传递重定向到程序而不是执行它

6ovsh4lw  于 2023-05-07  发布在  Shell
关注(0)|答案(2)|浏览(138)

我正试图让powershell调用一个带有构造参数列表的exe-并将响应通过管道传输到日志文件。我的问题是重定向字符似乎被传递到exe。(我也挣扎了近一天,以获得正确的引号周围的路径名,其中充满了空格!!!)
exe的语法为

filemeta  {-d|-i|-e} [-c] [-f=<directory name>] [-x=<file name>] [-v]
             [-p] [--] [--version] [-h] <file name> ...

你可以看到重复。我认为重定向被作为另一个文件名传递的原因首先是错误消息Cannot find file“〉〉”,其次是日志文件没有填充
粘贴到命令提示符中的以下命令将执行预期的操作。它只是如何让它 Package 在一个powershell文件迭代

"C:\Program Files\File Metadata\FileMeta.exe" -i -f="M:\metadata_XML_tobe\ManagedCatalog\Business Records\Morse Bakery"  "M:\ManagedCatalog\Business Records\Morse Bakery\Morse Bakery Book 1-000.JPG"  >>"M:\metadata_XML_tobe\apply_doc_id_20230412-124532.log" 2>>&1

Powershell命令到目前为止是…

$metaDataPath = 'M:\metadata_XML_tobe'
$timeStr = get-date -Format 'yyyyMMdd-HHmmss' 
$logFileName = $metaDataPath + "\apply_doc_id_" + $timeStr + ".log"
$files = Get-ChildItem -Path $metaDataPath -Recurse -Include *.xml
$quote = '"'
$hits  = 0
foreach ($f in $files){
    $hits++
    if ($hits -ge 5) {
        break
    }
    $directory = [System.IO.Path]::GetDirectoryName($f)
    $realFile_name = $f.FullName.Replace('.metadata.xml', '')
    $realFile_name = $realFile_name.Replace('\metadata_XML_tobe', '' )
    $parm1 = '-i'  
    $parm2 = '-f='+ $quote + $directory + $quote 
    $parm3 = $quote + $realFile_name + $quote
    $parm4 = ' >>'  
    $parm5 = $quote + $logFileName + $quote
    $parm6 = ' 2>>&1'  
    Write-Host '**************'
    Write-Host $f.FullName 
    Write-Host  '   Parm1   = ' $parm1
    Write-Host  '   Parm2   = ' $parm2
    Write-Host  '   Parm3   = ' $parm3
    Write-Host  '   Parm4   = ' $parm4
    Write-Host  '   Parm5   = ' $parm5
    Write-Host  '   Parm6   = ' $parm6
    echoargs 'C:\Program Files\File Metadata\FileMeta.exe' $parm1 $parm2 $parm3 $parm4 $parm5 $parm6
    # & 'C:\Program Files\File Metadata\FileMeta.exe' $parm1 $parm2 $parm3 $parm4 $parm5 $parm6
}

其输出为-----

M:\metadata_XML_tobe\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948\Baptism Records 1904-1948-003.JPG.metadata.xml
   Parm1   =  -i
   Parm2   =  -f="M:\metadata_XML_tobe\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948"
   Parm3   =  "M:\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948\Baptism Records 1904-1948-003.JPG"
   Parm4   =   >>
   Parm5   =  "M:\metadata_XML_tobe\apply_doc_id_20230417-105352.log"
   Parm6   =   2>>&1
Arg 0 is <C:\Program Files\File Metadata\FileMeta.exe>
Arg 1 is <-i>
Arg 2 is <-f=M:\metadata_XML_tobe\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948>
Arg 3 is <M:\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948\Baptism Records 1904-1948-003.JPG>
Arg 4 is < >>>
Arg 5 is <M:\metadata_XML_tobe\apply_doc_id_20230417-105352.log>
Arg 6 is < 2>>&1>

或者如果echoargs被换出

**************
M:\metadata_XML_tobe\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948\Baptism Records 1904-1948-003.JPG.metadata.xml
   Parm1   =  -i
   Parm2   =  -f="M:\metadata_XML_tobe\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948"
   Parm3   =  "M:\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948\Baptism Records 1904-1948-003.JPG"
   Parm4   =   >>
   Parm5   =  "M:\metadata_XML_tobe\apply_doc_id_20230417-105958.log"
   Parm6   =   2>>&1
Imported metadata to M:\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948\Baptism Records 1904-1948-003.JPG from M:\metadata_XML_tobe\ManagedCatalog\Church Records\Catholic Church Euroa\Baptism Records\1904-1948\Baptism Records 1904-1948-003.JPG.metadata.xml
Cannot find file " >>"

请帮助我理解这个迷宫
JC

dgtucam1

dgtucam11#

与任何shell一样,metacharacters(如>)不被使用 * 字面上,未加引号 * 不被视为这样:

# OK: > $null redirects the success-stream output to $null, i.e. 
#     *discards* it:
# NO OUTPUT, as expected.
Write-Output hi > $null

对比

# !! Due to saving *string* value '> $null' in a variable
# !! and passing that variable, its *verbatim value* is passed.
# OUTPUTS 'hi' and '> $null'
$var = '> $null'
Write-Output hi $var

也就是说,使用 variables 为给定的目标可执行文件指定单个 pass-through arguments,与尝试通过变量传递整个redirectionexpressions(如>> file)有根本的不同。
换句话说:不能使用变量传递具有 * syntax * function的命令行元素,例如>|

为了让PowerShell能够识别重定向 * 操作符 >>>),必须指定 * 字面意思,不加引号,而**您可以自由地将重定向 * 目标文件 (或$null以抑制输出)作为变量传递*;例如:

# Define the redirection target (output file) as a variable.
$file = 'temp file.txt'

# Now pass the variable to the - unquoted - > operator.
Write-Output hi > $file

但是,如果重定向目标是另一个 stream 的编号(例如,2>&1,以便将错误流(2)合并到成功流(1)),则该编号不能 * 通过变量指定。

$streamNumber = 1

# !! Does NOT work and triggers a *syntax error*:
# !! -> "Missing file specification after redirection operator."
Write-Output hi 2>&$streamNumber

但是,请注意,PowerShell只支持1-即 success 输出流-作为重定向目标。
如果你真的需要通过包含重定向 * 运算符 * 作为其值的一部分的变量来指定整个重定向 * 表达式 ,请继续阅读以获得解决方案。
如果你确实需要通过 * 变量
指定 * 任意重定向表达式 *,你可以使用Invoke-Expression(不过它是generally to be avoided):

# Define the command to invoke with all its arguments, but without redirections,
# as a script block ({ ... }), to be invoked later.
# The block may contain *multiple* statements.
$scriptBlock = { Write-Output hi }

# Define the desired redirection expression as a variable.
$redirection = '> $null'

# This is now the equivalent of:
#   & { Write-Output hi } > $null
# or, given that there's just *one* command in the script block:
#   Write-Output hi > $null
# Note the need to escape the $ in $scriptBlock as `$, 
# so as to prevent *up-front* expansion of the variable reference.
Invoke-Expression "& `$scriptBlock $redirection"
hl0ma9xz

hl0ma9xz2#

谢谢mklement 0(这不是一个答案,但它是太长的评论-对不起)我想我明白你说的重定向符号;如果它们不是字面上的,那么它们被视为变量。我似乎已经结束了这种方式,因为我不能形成'-f=directory'没有连接在一起,所以如果我必须把它放在一个变量,那么为什么不'-i'和'〉〉'以及。然后,它们都被相同地处理。但你能帮我理解一些其他的差异,以及从所有这些试验我想出了一些'规则',它会真的帮助我,如果你能确认或纠正我的理解注:我假设任何路径的名称中都可以有空格

& "C:\Program Files\File Metadata\FileMeta.exe" -i $parm2 $parm3  *>> $logFileName
     & "C:\Program Files\File Metadata\FileMeta.exe" -i $parm2 $parm3  *>> $logFileName
     | _____________________________________________ ----------------- ___ -----------------
     1              2                                       3           4        5
1 = The command or verb
2 = what to call. Can use single or double quotes
3 = anything up to pipe or redirect characters. MUST use DOUBLE quotes around paths
    even though these are stripped out. If you use single quotes you get an error like <Cannot find directory for arg Argument: f>
4 = Pipe or redirect chracters. Must be in the clear (not part of a variable)
5 = file names etc after the redirects.  MUST NOT use either double or single quotes - even if there are spaces in the path

然后还有其他的困惑-来自不同职位的想法在这里不起作用。举个例子
$logFileName 2〉〉&1“重定向操作符后缺少文件规范。”但是 *〉〉$logFileName可以工作。
难怪我感到困惑。这件事是不同质的,所以我真的不知道什么时候使用哪一套规则。谢谢期待JC

相关问题