我正在创建一个批处理文件,以便为程序输入获取拖放文件夹。一切都工作正常,直到我通过一个文件夹,为了这篇文章,这个文件名为foo&bar
。
检查批处理文件中包含的%1
看起来像C:\path\to\foo
或C:\path\to\foo\foo
。如果文件路径是引号,它将起作用,因此唯一有效的代码是:
set arg1=%1
cd %arg1%*
set arg1="%CD%"
使用通配符将目录更改为传递的参数。但是,如果父文件夹中有另一个包含未转义字符的文件夹,则只能运行一次,传递子文件夹会导致父文件夹的值。
我尝试the answer of this post,建议在@echo on
序列期间使用remark和redirection语句输出参数。但是在纠正问题方面没有取得任何进展。有什么建议吗?
回顾一下,我正在寻找方法将带有未转义字符的文件夹作为批处理文件的参数传递。实现应该最好是在批处理文件中,但欢迎使用VBScript的答案。但是,启动程序必须是批处理的,因为这是3接受文件作为参数的唯一程序。
要对此进行测试,请使用以下代码创建批处理文件:
@echo off
set "arg1=%~1"
echo "the passed path was %arg1%"
pause
然后创建名为foobar
和foo&bar
的文件夹。将它们拖到批处理文件中以查看其输出。 foo&bar
只会返回C:\path\to\foo
。
答案 0 :(得分:4)
好的,问题是资源管理器将其作为命令行传递给cmd.exe:
C:\Windows\system32\cmd.exe /c ""C:\path\test.bat" C:\path\foo&bar"
最外面的引号被剥离,命令变为
"C:\working\so46635563\test.bat" C:\path\foo&bar
cmd.exe与
类似地解释("C:\working\so46635563\test.bat" C:\path\foo) & bar
即,bar
被认为是一个单独的命令,要在批处理文件之后运行。
最好的解决方案是不要直接拖放到批处理文件上,而是拖放到vbscript或Powershell脚本或普通的旧可执行文件上。然后该脚本可以运行批处理文件,或者适当地引用参数,或者将目录路径放入环境变量而不是命令行。
或者,您可以从%CMDCMDLINE%
检索原始命令字符串,如下所示:
setlocal EnableDelayedExpansion
set "dirname=!CMDCMDLINE!"
set "dirname=%dirname:&=?%"
set "dirname=%dirname:" =*%"
set "dirname=%dirname:"=*%"
set "dirname=%dirname: =/%"
for /F "tokens=3 delims=*" %%i in ("%dirname%") do set dirname=%%i
set "dirname=%dirname:/= %"
set "dirname=%dirname:?=&%"
set dirname
pause
exit
注意最后的exit
;这是必要的,以便cmd.exe在到达脚本末尾时不会尝试运行bar
。否则,如果&
之后的目录名称部分恰好是有效命令,则可能会造成麻烦。
注意:我不确定这个剧本有多强大。
我用最明显的组合测试了它,但YMMV。 [专门使用延迟扩展可能更明智,我不确定。除了第一个set
命令外,它似乎似乎是必要的。如果你要走这条路线,Jeb's answer here可能是更好的选择。]
对于好奇,脚本的工作方式如下:
dirname
[由jeb指出的原因所必需] &
个字符替换为?
*
注意:有必要抑制空间来处理路径包含空格的情况(在这种情况下,资源管理器会在其周围添加引号)以及它不包含的情况。
/
注意:?
*
和/
在文件名中是非法的,因此这些替换是安全的。
此时字符串如下所示:
C:\Windows\system32\cmd.exe//c/**C:\path\test.bat**C:\path\foo?bar**
所以我们只需要拉出第三个星号分隔的元素,将任何正斜杠转回空格,任何问号都会标记回&符号,我们就完成了。呼!