![](/img/trans.png)
[英]Call a batch file from PowerShell with proper exit code reporting while avoiding doubling of carets
[英]Why do carets vanish when calling a batch file from powershell?
这是我的args.bat
文件:
@echo off
python -c "import sys; print(sys.argv)" %*
我在这里调用python是因为我确切地知道如何解释输出,而不是猜测字符串中的引号
如果我从cmd调用它,将会发生以下情况:
>.\args.bat ^^^^^
More?
More?
['-c', '^']
>.\args.bat "^^^^^"
['-c', '^^^^^']
但是,这是powershell的作用:
PS> .\args.bat ^^^^^
['-c', '^']
PS> .\args.bat "^^^^^"
['-c', '^']
PS> .\args.bat '^^^^^'
['-c', '^']
PS> .\args.bat "'^^^^^'"
['-c', '^']
PS> .\args.bat '"^^^^^"'
['-c', '^^^^^']
从Powershell调用批处理文件时,为什么必须双引号引用参数?
从powershell调用python并不存在相同的问题:
PS> python -c "import sys; print(sys.argv)" "^^^^^"
['-c', '^^^^^']
PS> python -c "import sys; print(sys.argv)" '^^^^^'
['-c', '^^^^^']
PS> python -c "import sys; print(sys.argv)" ^^^^^
['-c', '^^^^^']
但是从powershell从python调用批处理时仍然存在!
PS> python -c "import subprocess; subprocess.call(['args.bat', '^^^^^'])"
['-c', '^']
并从cmd的python批处理:
> python -c "import subprocess; subprocess.call(['args.bat', '^^^^^'])"
['-c', '^']
有关批处理文件是否可以可靠地传递任意参数的更大问题(损坏警报:否),请参阅Eric的后续问题 。
tl; dr :
PS> .\args.bat --% "^^^^^"
['-c', '^^^^^']
使用--%
(停止分析符号) ,使PowerShell可以按原样传递其余参数,除了扩展cmd.exe
样式的环境变量引用(例如%OS%
。
相反,您将无法引用PowerShell变量或表达式。
PowerShell作为本身的外壳,首先执行其自身的解析,然后(在Windows上这是不幸的必要)在为外部程序编写命令行时重新引用 。
这样做的方式已经随着时间而改变,并且在过去一直是许多问题的根源。 这些问题导致引入--%
,如上所述,但是有其自身的挑战。
但是,考虑到外部程序未必一定会理解PowerShell的语法,通常必须重新报价。
最值得注意的是,不能假定所有外部程序都理解'...'
引用,因此需要转换为"..."
。
但是,PowerShell根据是否认为必要而 有条件地重新报价。
在手的情况下,因为PowerShell中的内容 "^^^^^"
字符串包含没有空格 ,PowerShell的决定不通过批处理文件时,它引用它 ; 即:
.\args.bat "^^^^^"
有效地成为
.\args.bat ^^^^^
这对于大多数外部程序都很好,其中^
没有语法含义,但是在批处理文件(由cmd.exe
解释)的情况下,它很重要,因为^
用作转义符。 以不带引号的字符串存在。
要在这种情况下仍然强制使用双引号,作为上面的--%
方法的替代方法,可以使用嵌入式双引号,如您在问题中已经演示的:
PS> .\args.bat '"^^^^^"' # '...' quoting with embedded "..." quoting
['-c', '^^^^^']
从powershell调用python并不存在相同的问题:
PS> python -c "import sys; print(sys.argv)" "^^^^^"
这是因为在这种情况下不涉及cmd.exe
,即使从PowerShell调用时括起来的双引号丢失了,Python也会将^
实例视为文字。
但是从powershell从python调用批处理时仍然存在
PS> python -c "import subprocess; subprocess.call(['args.bat', '^^^^^'])"
然后从cmd的python批处理:
> python -c "import subprocess; subprocess.call(['args.bat', '^^^^^'])"
那是因为您要再次调用一个批处理文件-在这种情况下甚至从cmd.exe
^^^^^
使用未引号的 ^^^^^
,因为封闭的'....'
对Python仅具有语法意义,并且不会通过-重新介绍了^
的特殊解释。
请注意, 即使是调用批处理文件的“无壳”方法(例如Python中的subprocess.call()
)也始终会调用cmd.exe
,因为cmd.exe
是执行批处理文件所需的解释器。
将未加引号的字符串^^^^^
传递到批处理文件时,似乎有两轮解释:首先,作为参数解析的一部分,每对^^
变为单个^
,所有不成对的^
被丢弃。 因此, 在批处理文件中 ,您会看到^^
,当不加引号时,它会变成单个^
-如果在批处理文件中对%*
或%1
双引号,则会看到^^
被传递。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.