我已经用数十种语言进行编程 20 年了,但无论我多么努力,我都无法理解 Windows cmd shell 批处理文件中的“FOR”是如何工作的。 我读了
http://www.amazon.com/Windows-Administration-Command-Line-Vista /dp/0470046163/ref=sr_1_1?ie=UTF8&s=books&qid=1241362727&sr=8-1
http://www.ss64.com/nt/for.html
和互联网上的其他几篇文章,但仍然令人困惑并且无法完成任何事情。
有人能给我一个关于“FOR”一般如何工作的简洁解释吗?
对于一个更具体的问题,如何迭代 %PATH% 变量中的每个路径?
我试过
rem showpathenv.bat
for /f "delims=;" %%g in ("%PATH%") do echo %%g
只显示第一条路径,而不是全部。 为什么 ? 我做错了什么?
I've been programming in dozens of languages for 20 years but I could never understand how "FOR" work in windows cmd shell batch file, no matter how hard I tried. I read
http://www.amazon.com/Windows-Administration-Command-Line-Vista/dp/0470046163/ref=sr_1_1?ie=UTF8&s=books&qid=1241362727&sr=8-1
http://www.ss64.com/nt/for.html
and several other articles on the internet but still confuse and cannot accomplish anything.
Can anybody give me a concise explaination on how "FOR" works in general ?
For a little more specific question, how can I iterate through each path in %PATH% variable ?
I've tried with
rem showpathenv.bat
for /f "delims=;" %%g in ("%PATH%") do echo %%g
That'd show only the first path, not all of them. Why ? What I do wrong ?
发布评论
评论(12)
没有一个答案实际上有效。 我自己设法找到了解决方案。
这有点hackish,但它为我解决了问题:
哦! 我讨厌批处理文件编程!
更新
马克的解决方案更简单,但它不适用于包含空格的路径。 这是马克解决方案的稍作修改的版本
None of the answers actually work. I've managed to find the solution myself.
This is a bit hackish, but it solve the problem for me:
Oh ! I hate batch file programming !!
Updated
Mark's solution is simpler but it won't work with path containing whitespace. This is a little-modified version of Mark's solution
马克的想法很好,但也许忘记了一些路径中有空格。 替换 ';' with '" "' 相反会将所有路径切割成带引号的字符串。
所以这里显示了您的路径。
cmd 中的 FOR 命令有一个繁琐的学习曲线,特别是因为变量在 () 语句中如何反应...您可以分配任何变量,但不能在 () 中读回,除非您使用“ setlocal ENABLEDELAYEDEXPANSION”语句,因此也使用带有 !! 的变量而不是 %% 的 (!_var!)
我目前只使用 cmd 编写脚本,为了工作,必须学习所有这些:)
Mark's idea was good, but maybe forgot some path have spaces in them. Replacing ';' with '" "' instead would cut all paths into quoted strings.
So here, you have your paths displayed.
FOR command in cmd has a tedious learning curve, notably because how variables react within ()'s statements... you can assign any variables, but you can't read then back within the ()'s, unless you use the "setlocal ENABLEDELAYEDEXPANSION" statement, and therefore also use the variables with !!'s instead of %%'s (!_var!)
I currently exclusively script with cmd, for work, had to learn all this :)
您的想法是正确的,但是
for /f
旨在处理多行文件或命令,而不是单个字符串。在最简单的形式中,
for
就像 Perl 的for
或所有其他语言的foreach
。 您向它传递一个标记列表,它会迭代它们,每次都调用相同的命令。这些扩展仅提供构建令牌列表的自动方法。 当前代码没有任何结果的原因是“
;
”是默认的行尾(注释)符号。 但即使您更改它,您也必须使用%%g, %%h, %%i, ...
来访问各个令牌,这将严重限制您的批处理文件。您可以得到的最接近您所要求的内容是:
但是对于包含分号的引用路径来说,这将失败。
根据我的经验,
for /l
和for /r
非常适合扩展现有命令,但for
则非常有限。 您可以通过延迟变量扩展(cmd /v:on
)使其功能稍微强大(并且令人困惑),但它实际上只适用于文件名列表。如果您需要执行字符串操作,我建议使用 WSH 或 PowerShell。 如果您尝试为 Windows 编写
whereis
,请尝试where /?
。You've got the right idea, but
for /f
is designed to work on multi-line files or commands, not individual strings.In its simplest form,
for
is like Perl'sfor
, or every other language'sforeach
. You pass it a list of tokens, and it iterates over them, calling the same command each time.The extensions merely provide automatic ways of building the list of tokens. The reason your current code is coming up with nothing is that '
;
' is the default end of line (comment) symbol. But even if you change that, you'd have to use%%g, %%h, %%i, ...
to access the individual tokens, which will severely limit your batch file.The closest you can get to what you ask for is:
But that will fail for quoted paths that contain semicolons.
In my experience,
for /l
andfor /r
are good for extending existing commands, but otherwisefor
is extremely limited. You can make it slightly more powerful (and confusing) with delayed variable expansion (cmd /v:on
), but it's really only good for lists of filenames.I'd suggest using WSH or PowerShell if you need to perform string manipulation. If you're trying to write
whereis
for Windows, trywhere /?
.忍不住把它扔在那里,因为这个线程很旧......通常当需要迭代 PATH 中的每个文件时,你真正想做的就是找到一个特定的文件......如果是这种情况,这个单行将吐出它在其中找到文件的第一个目录:(
例如:寻找 java.exe)
Couldn't resist throwing this out there, old as this thread is... Usually when the need arises to iterate through each of the files in PATH, all you really want to do is find a particular file... If that's the case, this one-liner will spit out the first directory it finds your file in:
(ex: looking for java.exe)
我知道这太老了......但只是为了好玩,我决定尝试一下:
这不需要计数,并且会一直进行到完成为止。 我对空格也有同样的问题,但它通过了整个变量。 关键是循环标签和 SHIFT 函数。
I know this is SUPER old... but just for fun I decided to give this a try:
This doesn't require a count and will go until it finishes. I had the same problem with spaces but it made it through the entire variable. The key to this is the loop labels and the
SHIFT
function.for /f
迭代每行输入,因此在您的程序中只会输出第一个路径。你的程序将%PATH%视为单行输入,并以
;
分隔,将第一个结果放入%%g,然后输出%%g(第一个分隔路径)。for /f
iterates per line input, so in your program will only output first path.your program treats %PATH% as one-line input, and deliminate by
;
, put first result to %%g, then output %%g (first deliminated path).FOR
本质上是对数据集中的“行”进行迭代。 在本例中,有一行包含路径。"delims=;"
只是告诉它以分号分隔。 如果将正文更改为echo %%g,%%h,%%i,%%j,%%k
,您会发现它将输入视为单行并中断它分成多个令牌。FOR
is essentially iterating over the "lines" in the data set. In this case, there is one line that contains the path. The"delims=;"
is just telling it to separate on semi-colons. If you change the body toecho %%g,%%h,%%i,%%j,%%k
you'll see that it is treating the input as a single line and breaking it into multiple tokens.这对我有用:
This works for me:
您还必须额外使用
for
循环允许的选项的tokens=1,2,...
部分。 这里将执行您可能想要的操作:此示例仅处理前 12 个标记(=%path% 中的目录)。 它使用每个使用的标记的显式枚举。 请注意,令牌名称区分大小写:%a 与 %A 不同。
要保存带有空格的路径,请将全部 %x 用引号括起来,例如“%i”。 我没有在这里这样做,我只是回应标记。
你也可以做某事。 像这样:
这个跳过标记 2,4,6 并使用一个小快捷方式(“
7-26
”)来命名其余的标记。 请注意,与第一个示例相比,这次如何以相反的顺序处理 %c、%b、%a,以及它们现在如何“表示”不同的标记。所以这肯定不是您要求的简洁解释。 但也许这些例子现在有助于更好地澄清......
You have to additionally use the
tokens=1,2,...
part of the options that thefor
loop allows. This here will do what you possibly want:This example processes the first 12 tokens (=directories from %path%) only. It uses explicit enumeration of each of the used tokens. Note, that the token names are case sensitive: %a is different from %A.
To be save for paths with spaces, surround all %x with quotes like this "%i". I didn't do it here where I'm only echoing the tokens.
You could also do s.th. like this:
This one skips tokens 2,4,6 and uses a little shortcut ("
7-26
") to name the rest of them. Note how %c, %b, %a are processed in reverse order this time, and how they now 'mean' different tokens, compared to the first example.So this surely isn't the concise explanation you asked for. But maybe the examples help to clarify a little better now...
这是一个很好的指南:
FOR /F - 循环命令:针对一组文件。
FOR /F - 循环命令:针对另一个命令的结果。
FOR - 循环命令:所有选项文件、目录、列表。
[整个指南(Windows XP 命令) ):
http://www.ss64.com/nt/index.html
<强>编辑:抱歉,没有看到该链接已经在OP中,因为它在我看来是亚马逊链接的一部分。
Here is a good guide:
FOR /F - Loop command: against a set of files.
FOR /F - Loop command: against the results of another command.
FOR - Loop command: all options Files, Directory, List.
[The whole guide (Windows XP commands):
http://www.ss64.com/nt/index.html
Edit: Sorry, didn't see that the link was already in the OP, as it appeared to me as a part of the Amazon link.
这对我有用,试试吧。
It works for me, try it.
这对我有用,试试吧。
对于/f“令牌=* delims=;” %g in ('echo %PATH%') 执行 echo %g%
It works for me, try it.
for /f "tokens=* delims=;" %g in ('echo %PATH%') do echo %g%