如何在批处理文件中循环匹配通配符的文件

216

我有一组基本文件名,每个名称'f'都有两个文件,'f.in'和'f.out'。我想编写一个批处理文件(在Windows XP中),它可以遍历所有的文件名,并对每一个执行以下操作:

  • 显示基本名称'f'
  • 对'f.in'执行一个操作
  • 对'f.out'执行另一个操作

我没有任何方法来列出这组基本文件名,除了搜索*.in(或*.out)等文件。

7个回答

324

如果您有两个处理文件的程序,即process_in.exe和process_out.exe:

for %%f in (*.in) do (
    echo %%~nf
    process_in "%%~nf.in"
    process_out "%%~nf.out"
)

%%~nf是一个替换修饰符,它将%f扩展为仅文件名。 在https://technet.microsoft.com/en-us/library/bb490909.aspx中查看其他修饰符(在页面中间位置),或者查看下一个答案。


57
在命令行中输入时,只需使用一个百分号(%)。我知道原帖并没有提到命令行,但当我在谷歌搜索时,这个问题排名靠前就是我需要的答案。其他人可能也会感到有用。 - Jason
2
你能解释一下这个语法吗?循环变量被声明为 %%f,为什么后来变成了 %%~nf - Colonel Panic
6
@ColonelPanic - 这里有几个~修饰符可以用来执行一些操作,比如在我的示例中,只获取文件名。我习惯使用这个修饰符,以防*会获取完整路径或其他内容。这个页面中间部分列出了几个这样的修饰符:http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/batch.mspx?mfr=true - Jim Buck
如果文件和目录中有空格怎么办? - BenKoshy
3
请注意,%%f变量必须是单个字母 - 如果您尝试使用可读且有意义的内容,则会出现晦涩的错误消息。 - Bruce Dawson

106

您可以使用此命令打印您的桌面内容:

FOR %%I in (C:\windows\desktop\*.*) DO echo %%I 

一旦您拥有%%I变量,就可以轻松地对其执行命令(只需将单词echo替换为您的程序)。
此外,已增强 FOR 变量引用的替换功能。现在您可以使用以下可选语法:
%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only (directory with \)
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I to the
               fully qualified name of the first one found.
               If the environment variable name is not
               defined or the file is not found by the
               search, then this modifier expands to the
               empty string

https://ss64.com/nt/syntax-args.html

在上述示例中,%I和PATH可以替换为其他有效值。 %~语法由有效的FOR变量名称终止。选择大写变量名称(如%I)使其更易读,并避免与不区分大小写的修饰符混淆。
您可以通过键入FOR /?来获取完整文档。

1
这似乎不起作用。%%I在此时是意外的。 - Brad
8
如果您在命令行中使用它(而不是在批处理文件中),则请使用“%I”而不是“%%I”。 - doubleDown
1
一个比被接受的答案好得多的答案。所有标志/修饰符都包含在答案中,而不是第三方网站(没有人想点击你的链接,路易斯)。 - JustCarty

7

我认为最简单的方法是使用for循环调用第二个批处理文件进行处理,并将基本名称传递给第二个文件。

根据for /? 帮助文档,可以使用巧妙的~n选项提取基本名称。因此,基础脚本应该如下所示:

for %%f in (*.in) do call process.cmd %%~nf

然后,在process.cmd中,假设%0包含基本名称,并相应地采取行动。例如:

echo The file is %0
copy %0.in %0.out
ren %0.out monkeys_are_cool.txt

也许有更好的方法在一个脚本中执行多个命令,但我一直对如何在批处理文件中使用单个for循环执行多个命令感到有些困惑。

编辑:太棒了!我不知道文档中有一页显示可以在FOR循环中执行多行块。现在我需要回去重写一些批处理文件...


process.cmd 中的 %0 看起来包含了 process.cmd 本身。应该在 process.cmd 中使用 %1。 - Vlad Alex

4

Nathan 的帖子基础上,以下代码可以在一个批处理文件中完成整个任务。

@echo off

if %1.==Sub. goto %2

for %%f in (*.in) do call %0 Sub action %%~nf
goto end

:action
echo The file is %3
copy %3.in %3.out
ren %3.out monkeys_are_cool.txt

:end

3

有一个通常在微软服务器中使用的工具(据我所记)叫做forfiles

上面的链接包含帮助以及指向微软下载页面的链接。


2
下面的代码过滤以给定子字符串开头的文件名。通过处理子字符串提取和IF语句,可以更改它以适应不同的需求:
echo off
rem filter all files not starting with the prefix 'dat'
setlocal enabledelayedexpansion
FOR /R your-folder-fullpath %%F IN (*.*) DO (
set fname=%%~nF
set subfname=!fname:~0,3!
IF NOT "!subfname!" == "dat" echo "%%F"
)
pause

0

在 for /f 循环中,回显 f.in 和 f.out 将分离什么需要循环和什么不需要循环的概念。

::Get the files seperated
echo f.in>files_to_pass_through.txt
echo f.out>>files_to_pass_through.txt

for /F %%a in (files_to_pass_through.txt) do (
for /R %%b in (*.*) do (
if "%%a" NEQ "%%b" (
echo %%b>>dont_pass_through_these.txt
)
)
)
::I'm assuming the base name is the whole string "f".
::If I'm right then all the files begin with "f".
::So all you have to do is display "f". right?
::But that would be too easy.
::Let's do this the right way.
for /f %%C in (dont_pass_through_these.txt)
::displays the filename and not the extention
echo %~nC
)

虽然你没有问,但将命令传递到 f.in 和 f.out 的好方法是...

for /F %%D "tokens=*" in (dont_pass_through_these.txt) do (
for /F %%E in (%%D) do (
start /wait %%E
)
)

所有Windows XP命令的链接:link

如果我的回答不正确,我很抱歉。这个问题对我来说很难读懂。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接