我正在尝试让 powershell 调用带有构造参数列表的 exe - 并将响应通过管道传输到日志文件。 我的问题是重定向字符似乎传递给了 exe。 (我也挣扎了将近一天才在充满空格的路径名周围找到正确的引号!!!)
exe 的语法是
filemeta {-d|-i|-e} [-c] [-f=<directory name>] [-x=<file name>] [-v]
[-p] [--] [--version] [-h] <file name> ...
正如你所看到的重复。我认为重定向作为另一个文件名传递的原因首先是错误消息 找不到文件“>>” 其次,日志文件未填充
粘贴到命令提示符中的以下命令执行预期的操作。它只是如何将它包装在 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
与在任何 shell 中一样,元字符(例如
>
未使用 literally,unquoted 不会被这样处理:
# 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 与尝试传递 shell 重定向 根本不同,例如
>>
- 只有前者通过按原样引用变量来工作在命令行上。
如果您确实需要通过 variables 指定 redirections,您可以使用
Invoke-Expression
,这是 通常要避免的,但是:
# Define the command to invoke with all its arguments, but without redirections,
# as a script block ({ ... }), to be invoked later.
$scriptBlock = { Write-Output hi }
# Define the desired redirection as a variable.
$redirection = '> $null'
# This is now the equivalent of:
# Write-Output hi > $null
Invoke-Expression "& $scriptBlock $redirection"
谢谢 mklement0 (这不是答案,但评论太长了 - 抱歉) 我想我理解你所说的重定向符号;如果它们实际上不存在,那么它们将被视为变量。 我似乎以这种方式结束,因为如果不先将它们连接在一起,我就无法形成 '-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
然后还有其他混淆 - 来自不同帖子的想法在这里不起作用。例如
$日志文件名 2>>&1 “重定向运算符后缺少文件规范。” 但是 *>> $logFileName 确实有效。
难怪我很困惑。这东西不是同质的,所以我真的不知道什么时候使用哪一套规则。 感谢期待 杰西