【问题标题】:Microsoft batch file not passing arguments to subroutineMicrosoft批处理文件未将参数传递给子例程
【发布时间】:2016-10-05 13:26:47
【问题描述】:

以下批处理文件未正确地将变量 %%a、%%b、%%c 正确传递给子程序。

@echo off
enter code here`setlocal EnableDelayedExpansion

FOR /F "tokens=1,2,3 delims= " %%a in (ftp_config.txt) do (
  echo %%a
  echo %%b
  echo %%c
  call :SUB_ftp_cmd %%a %%b %%c
  )
exit

:SUB_ftp_cmd
echo open %1>ftp.txt
echo %2>>ftp.txt
echo %3>>ftp.txt
echo cd /public_html>>ftp.txt
echo bin>>ftp.txt
echo hash>>ftp.txt
echo put "test.txt">>ftp.txt
echo close>>ftp.txt
echo bye>>ftp.txt

c:\windows\system32\ftp.exe -i <ftp.txt

del ftp.txt

exit /b

ftp.config 包含以下内容:

domain_name1 username1 password1
domain_name2 username2 password2

ftp.txt 的内容最终是:

open 
ECHO is off.
ECHO is off.
cd /public_html
bin
hash
put "test.txt"
close
bye

我在调试中添加了几行代码,发现 %%a、%%b、%%c 在 FOR 循环中被正确分配,但没有正确传递给 SUB_ftp_cmd。

将批处理文件更新为:

@echo off
setlocal DisableDelayedExpansion
FOR /F "tokens=1,2,* delims=      " %%a in (ftp_config.txt) do (
  echo(=== for loop variables: a=[%%a], b=[%%b], c=[%%c]
    set "passw=%%c"
    call :SUB_ftp_cmd %%a %%b
  )
exit /B

:SUB_ftp_cmd
SETLOCAL EnableDelayedExpansion
>ftp.txt (
echo open %1
echo(%2
echo(!passw!
echo cd /public_html
echo bin
echo hash
echo put "test.txt"
echo close
echo bye
)
ENDLOCAL
echo(=== ftp.txt content
type ftp.txt
echo(=== ftp command is merely displayed using `ECHO`
ECHO c:\windows\system32\ftp.exe -i -s:ftp.txt
echo(
rem del ftp.txt
exit /b

ftp_config.txt 有:

"ftp.domain1.com" username1 pas3&^#%$
"ftp.domain2.com" username2 passworks

生成的 ftp.txt:

open "ftp.domain2.com"
username2

cd /public_html
bin
hash
put "test.txt"
close
bye

感谢任何帮助。

【问题讨论】:

  • ftp /? 表示应该使用ftp -i -s:ftp.txt 而不是ftp.exe -i &lt;ftp.txt。但是,您的脚本可能会使用setlocal DisableDelayedExpansion 正确运行,以在密码中保留可能的! 感叹号。我会使用 FOR /F "tokens=1,2,*" %%a in (ftp_config.txt) do …call :SUB_ftp_cmd %%a %%b "%%c"echo %~3&gt;&gt;ftp.txt

标签: windows batch-file ftp arguments


【解决方案1】:

如果ftp_config.txt 文件中有一个看似空的行,即使它包含(一个或多个)&lt;tab&gt;(字符列表),我也可以重现非常相似的结果。
让我们反对"tokens=1,2,3 delims= " 子句:

结论:使用"delims=&lt;tab&gt;&lt;No-Break Space&gt;&lt;space&gt;";就键盘输入而言(我不知道如何在这里显示更好的方法):“delims=TabAlt+0160Space ”。

即使密码包含cmd poisonous characters or valid delimiters,例如%&amp;|&lt;&gt;!,=、@98764,下一个脚本也应该可以工作@ 等(假设计算机名和用户名不包含这些),请参见下面的输出:

@echo off
setlocal DisableDelayedExpansion
rem FOR /F "tokens=1,2,*" %%a in (ftp_config.txt) do (
rem in next line     delims=<tab><No-Break Space><space>" %%a …
FOR /F "tokens=1,2,* delims=      " %%a in (ftp_config.txt) do (
  echo(=== for loop variables: a=[%%a], b=[%%b], c=[%%c]
    set "passw=%%c"
    call :SUB_ftp_cmd %%a %%b
  )
exit /B

:SUB_ftp_cmd
SETLOCAL EnableDelayedExpansion
>ftp.txt (
echo open %1
echo(%2
echo(!passw!
echo cd /public_html
echo bin
echo hash
echo put "test.txt"
echo close
echo bye
)
ENDLOCAL
echo(=== ftp.txt content
type ftp.txt
echo(=== ftp command is merely displayed using `ECHO`
ECHO c:\windows\system32\ftp.exe -i -s:ftp.txt
echo(
del ftp.txt
exit /b

输出

==> D:\bat\SO\37648941.bat
=== for loop variables: a=[domain_name1], b=[username1], c=[pass&,!%word1]
=== ftp.txt content
open domain_name1
username1
pass&,!%word1
cd /public_html
bin
hash
put "test.txt"
close
bye
=== ftp command is merely displayed using `ECHO`
c:\windows\system32\ftp.exe -i -s:ftp.txt

=== for loop variables: a=[domain_name2], b=[username2], c=[pass<;!%word2]
=== ftp.txt content
open domain_name2
username2
pass<;!%word2
cd /public_html
bin
hash
put "test.txt"
close
bye
=== ftp command is merely displayed using `ECHO`
c:\windows\system32\ftp.exe -i -s:ftp.txt

==>

【讨论】:

  • 感谢 JosefZ,这解决了传递域名和用户名的问题,但是,我仍然收到“ECHO 已关闭”。对于应该包含密码的行。 ftp_config.txt 文件不包含制表符,只有空格。密码确实包含一些特殊字符 [! | ^ |等],我需要正确处理密码的任何其他要求吗?
  • @ruaok 查看我的更新答案,注意echo(%2echo(!passw! 中的左括号。如果%2!passw! 为空,这将产生一个空的输出行来抑制ECHO is off 消息。请edit your question 并添加您的ftp_config.txtminimal reproducible example 和相应的输出,就像我在回答中所做的那样。
  • 您好 JosefZ,感谢您给予的详细关注。我用您提供的编辑更新了问题,但仍然看到密码有一些问题。在 echo(%2 和 echo(!passw! 中添加左括号将结果更改为 ftp.txt 中的密码为空行
  • 请注意echo(=== for loop variables: a=[%%a], b=[%%b], c=[%%c] 行。它在这里,但仅用于调试目的……
  • 指定"tokens=1,2,*" 完全省略delims。如果输出不正确,请确保您使用"delims=&lt;tab&gt;&lt;No-BreakSpace&gt;&lt;space&gt;"。请注意,某些文本编辑器倾向于将 &lt;tab&gt; 扩展为空格!
猜你喜欢
  • 2013-10-01
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
  • 2016-07-03
  • 2019-01-04
  • 1970-01-01
相关资源
最近更新 更多