批处理循环的正确定界符

时间:2018-09-20 22:22:43

标签: batch-file cmd

此代码:

@echo off
setlocal enableextensions enabledelayedexpansion
set "var=string"

set /P q="How many subdirectories would you like to add in each folder? "

for /l %%x in (1, 1, %q%) do (
    set /P c="What is the name of subdirectory %%x? "
    for /F "tokens=1 delims=\n" %%d IN (list.txt) DO md "%%d\!c!"
 )

基于列表文件创建文件夹,并根据用户输入将子目录添加到每个文件夹中。子目录创建正确,但是名称列表在定界符周围有一些时髦的行为。这是一个假设的列表:

7 Jonathon, Hasselhoff B
7 Dean, Granger P
7 Dean, Jimmy C
7 Norris, Chuck J
7 Chan, Jackie S

通过上面的代码运行此列表将产生以下文件夹名称:

7 Jo
7 Dea
7 Norris, Chuck J
7 Cha

如果我更改代码以使delims="可以正常工作。谁能解释为什么?

1 个答案:

答案 0 :(得分:1)

对于此任务,我建议使用以下批处理文件:

@echo off
setlocal EnableExtensions EnableDelayedExpansion

:GetFolderCount
set "FolderCount="
set /P "FolderCount=How many subdirectories would you like to add in each folder? "
rem Has the user entered anything at all?
if not defined FolderCount goto GetFolderCount
rem Has the user entered a string not consisting only of digits?
for /F delims^=0123456789^ eol^= %%I in ("!FolderCount!") do goto GetFolderCount
rem Has the user entered a positive integer too large for Windows command
rem processor or being interpreted octal by cmd.exe because of leading zeros?
set /A TempCount=FolderCount
if not %TempCount% == %FolderCount% goto GetFolderCount
set "TempCount="

if not %FolderCount% == 0 (
    for /L %%I in (1,1,%FolderCount%) do (
        set "FolderName="
        set /P "FolderName=What is the name of subdirectory %%I? "
        if defined FolderName for /F "eol=| delims=" %%J in (list.txt) do md "%%~J\!FolderName!"
    )
)

endlocal

批处理文件不相信用户输入的内容总是正确的正整数。因此,批处理文件首先删除环境变量FolderCount

接下来,它会提示批处理文件用户输入子目录数。如果用户只是按下 RETURN ENTER 导致再次提示用户,则FolderCount仍未定义。还可以在提示用户设置默认值之前,通过按 RETURN 键,用FolderCount之类的值来定义1 ENTER

用户可以有意输入或错误输入任何字符串,而不仅仅是批处理文件期望的正整数。因此,接下来需要验证输入的字符串实际上仅包含数字。

使用选项/F

FOR 会忽略空字符串(不再可能)和以;开头的字符串。输入的以分号开头的字符串应被解释为错误的输入,这是将默认eol=;重新定义为eol=来定义无行尾字符的原因,因此不要忽略与字符串无关的字符串第一个字符。

FOR 使用默认空格和水平制表符作为子字符串的分隔符,将字符串拆分为子字符串(令牌),并仅将第一个子字符串分配给指定的循环变量I。通过用delims=0123456789指定所有数字作为分隔符,可以修改此字符串拆分行为。如果用户输入的字符串仅由数字组成,则 FOR 循环将不执行命令 GOTO ,因为在这种情况下,不能为循环变量I分配任何内容。但是,如果用户输入的字符串中还有其他任何字符,则 GOTO 命令将由 FOR 执行,在这种情况下,会将某些内容分配给循环变量。

使用另一种非双引号方法来定义定界符列表,并且不使用行尾字符,这要求使用字符插入符号^来转义两个等号和两个选项之间的空格字符这样,根据 FOR 语法的要求,整个选项字符串将被解释为一个参数字符串。

通过此检查后,用户输入的字符串肯定仅包含数字。

但是它可以有前导零,从而导致解释八进制数或该数字太大,如439871023842。因此,使用算术表达式将用户输入的字符串分配给另一个环境变量,在这种情况下,该结果导致将用户输入的字符串转换为值范围为02147483647的32位有符号整数因为-开头已经不可能了。接下来,将所得的整数转换回分配给环境变量TempCount的字符串。因此,如果分配给TempCount的字符串不等于分配给FolderCount的字符串,则用户输入的值将不满足作为正32位十进制整数值的要求。

仍然可能的是,用户输入了0作为子目录的数目,在这种情况下,根本不会执行下一个块,而根据用户的输入则无所事事。

在循环中提示用户输入文件夹名称之前,始终会删除环境变量FolderName。因此,用户必须始终输入文件夹名称,否则将无法进行任何操作。如果应该再次使用子目录的先前输入名称,则用户可以使用键 UP 一次或多次。

在用户输入一个非空字符串后,将按预期创建子目录,该字符串对于当前目录中文件list.txt中定义的每个子目录中的文件夹名称均有效。

这次使用选项/Flist.txt修改了带有选项eol=| FOR 命令以从文件delims=读取行在双引号参数字符串中指定,由于指定了空的定界符列表,因此不会忽略以分号开头的行,也不会将每一行拆分为子字符串。竖线代替;,因为文件夹名称不能包含竖线,而文件夹名称开头可以使用分号。

因此,您已经用delims=\n定义了反斜线或字母n上的行,而以delims=结尾的可选参数字符串定义了一个空的定界符列表,从而关闭了字符串/行如果不以竖线开头,则完全拆分行为并将其分配给指定的循环变量J始终是从列表文件读取的整个非空行。

注意:由于启用了延迟的环境变量扩展,list.txt中包含一个或多个感叹号的目录名称未正确处理。但这似乎没问题。

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • md /?
  • rem /?
  • set /?
  • setlocal /?