【发布时间】:2010-09-07 13:34:04
【问题描述】:
我有一组基本文件名,每个名称“f”都有两个文件,“f.in”和“f.out”。我想为每个文件名编写一个批处理文件(在 Windows XP 中),它应该:
- 显示基本名称“f”
- 对“f.in”执行操作
- 对“f.out”执行另一项操作
除了搜索 *.in(或 *.out)之外,我没有任何方法可以列出基本文件名集。
【问题讨论】:
标签: command-line windows-xp batch-file
我有一组基本文件名,每个名称“f”都有两个文件,“f.in”和“f.out”。我想为每个文件名编写一个批处理文件(在 Windows XP 中),它应该:
除了搜索 *.in(或 *.out)之外,我没有任何方法可以列出基本文件名集。
【问题讨论】:
标签: command-line windows-xp batch-file
假设您有两个程序处理这两个文件,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(页面中间)或下一个答案中查看其他修饰符。
【讨论】:
%%f,为什么后面是%%~nf?
~ 修饰符可以做一些事情,就像在我的示例中一样,只需获取文件名。我习惯使用它,以防* 完成完整路径或其他内容。有一些修饰符(页面中间):microsoft.com/resources/documentation/windows/xp/all/proddocs/…
您可以使用此行打印桌面的内容:
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 /?获取完整文档
【讨论】:
%%I was unexpected at this time.
%I 而不是 %%I
在我看来,最简单的方法是使用 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 循环中执行多行块的页面。我要回去了,现在要重写一些批处理文件……
【讨论】:
在Nathans 帖子上展开。以下将在一个批处理文件中完成大量工作。
@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
【讨论】:
有一个工具通常用于 MS 服务器(据我所知),称为 forfiles:
上面的链接包含帮助以及指向 microsoft 下载页面的链接。
【讨论】:
下面的代码过滤以给定子字符串开头的文件名。可以通过处理 subfname 子字符串提取和 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
【讨论】:
在 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
如果我没有正确回答这个问题,我深表歉意。这个问题对我来说很难读。
【讨论】: