在DOS批处理脚本中填充数组


33

如何在DOS批处理脚本中设置数组变量?我想用要处理的文件名列表加载它。我真的很想让它尽可能简单。谢谢。


1
真的需要与DOS兼容,还是可以使用PowerShell?
Brian Knoblauch

1
您也可以很容易地使用vbscript ...
JNK 2010年

@Brian:需要DOS。查看我发布的解决方案。
Jim Fell 2010年

如果您没有头发,那么您当然应该知道命令提示符和DOS之间的区别
barlop

Answers:


48

我想到了:

set FILE_LIST=(file1.dll file2.exe file3.dll file4.dll file5.dll)

set BIN_PATH="C:\Program Files\My App Folder\bin"
set BAK_PATH="C:\Program Files\My App Folder\bin\Backups"
set DEV_PATH="C:\My Dev Path\bin\Debug"

for %%i in %FILE_LIST% do copy %BIN_PATH%\%%i %BAK_PATH%
for %%i in %FILE_LIST% do copy %DEV_PATH%\%%i %BIN_PATH%

几年前我做了类似的事情,所以就花了点时间。(顺便说一句,我讨厌重新发明轮子。)既然已经在这里发布了,希望其他人也能找到它。


1
好吧,我不知道你能做到!我试过了,它有效!
Linker3000

这可能无法在DOS中工作。DOS不会做长文件名(只有8.3),而且我记得,DOS也不在文件路径中加引号。我没有方便的MS-DOS安装,以查看它是否支持使用()语法的数组。
2014年

3
尽管这样做确实可以满足您的目的,但应注意,它实际上不是数组。它只是一个字符串,被拆分为单个元素。您无法通过执行类似操作来直接引用元素FILE_LIST[0]
Aphoria 2014年

@MichaelKjörling:FreeDOS 可以支持LFN和大概的引号,所以也许他正在使用它?
内森·塔吉

@NathanTuggy好点。不过,在这种情况下,最好将其明确化。
CVn 2015年

12

是的,您可以批量处理阵列。尽管它们与C或VB中的数组不完全相同,但是您可以这样做:

@echo off
setlocal enabledelayedexpansion

set  arrayline[0]=############
set  arrayline[1]=#..........#
set  arrayline[2]=#..........#
set  arrayline[3]=#..........#
set  arrayline[4]=#..........#
set  arrayline[5]=#..........#
set  arrayline[6]=#..........#
set  arrayline[7]=#..........#
set  arrayline[8]=#..........#
set  arrayline[9]=#..........#
set arrayline[10]=#..........#
set arrayline[11]=#..........#
set arrayline[12]=############

::read it using a FOR /L statement
for /l %%n in (0,1,12) do (
echo !arrayline[%%n]!
)
pause

1
这是真棒,inspring ..我只是做到了建立在这一点,填充答案数组太
barlop

7

在Jakash3的Blog中,批处理数组描述了如何在命令提示符下模拟数组。

本文中包含一个名为array.bat的批处理文件,该文件包含用于处理数组的函数库。您将需要选择文章中的文本并将其粘贴到bat文件中。

例如,以下测试脚本:

@echo off
set book[0]=Avatar
set book[1]=The Green Mile
set book[2]=The Count of Monte Cristo
call array.bat add book Babo
call array.bat len book length
echo I have %length% books you can borrow.
echo Pick one:
echo.
echo 0) Avatar
echo 1) The Green Mile
echo 2) The Count of Monte Cristo
echo 3) Babo
echo.
set /p pick=
call array.bat getitem book %pick% title
echo.
echo You picked %title%.

生成以下输出:

图片


1
好的,尽管您没有列出array.bat的内容,尽管我看到它有点长
barlop 2013年

4

这将填充一个数组并进行打印

您可以通过写名称来使用名称1名称2名称3,而不是名称[1]名称[2]名称[3]!而不是名称[!i!]。它通过生成变量名来生成数组。没有批量的数组结构。但这就像任何数组结构一样整齐,填充或打印看起来就像是用一种合适的语言(实际上具有数组结构!)填充或打印数组一样。

@echo off
setlocal enabledelayedexpansion enableextensions

set i=-1

for %%f in (bob, tom, joseph) do (
 set /a i=!i!+1
 set names[!i!]=%%f
)
set lastindex=!i!

for /L %%f in (0,1,!lastindex!) do ( 
  echo !names[%%f]!
)

输出-

c:\blah>a
bob
tom
joseph

c:\blah>

一些解释-

setlocal enabledelayedexpansion enableextensions用!VAR!而不是必须使用%var%来防止出现奇怪的行为,以便变量在FOR或IF中时可以正常运行。批处理文件很奇怪。查看set /?进一步提到的地方。

这就是填充数组的原因,对于任何了解数组的人来说都是很直接的。您也可以做到,names[0]=bob names[1]=tom names[2]=joseph尽管数组的优点之一是可以用循环填充数组,这就是我在这里所做的。

for %%f in (bob, tom, joseph) do (
 set /a i=!i!+1
 set names[!i!]=%%f
)
set lastindex=!i!

这将显示阵列。%% f如果您回显它,您会看到它将从0到数组的最后一个索引,以1为步长,因此将打印名称[0]名称[1]名称[2]

for /L %%f in (0,1,!lastindex!) do ( 
  echo !names[%%f]!
)

0

对于您想做的事情,如何为每个文件名使用输入变量,您可以使用%1%2等变量来取值,例如:mybat.bat file1.nam file2.nam等。

然后,您可以在循环中使用这些变量,但只需要使用%1作为主要参数,因为您可以使用SHIFT将其他变量带入%1'位置',并测试是否有空值(变量的结尾)就像IF“ X%1” ==“ X”

例如:

:LOOP
IF "X%1" == "X" GOTO DONE
COPY %1 C:\TARGET.DIR
SHIFT
GOTO LOOP
:DONE

0

如果将文件列表保存到filelist.txt,则可以FOR读取和处理文件的每一行,例如

FOR /F "delims=|" %i  IN (filelist.txt) DO @echo %i

打印文件的每一行(直到该行的第一个“ |”。如果您未指定自己的定界符,将使用空格和制表符,因此,除非您的路径没有空格,否则需要指定一个字符不会出现在文件中以获取完整的行)。


/ f实际上是Windows 2000及更高版本的功能。它不在DOS中。
wendy.krieger 2014年

0

在您对某个答案的评论中,您说:

我正在进行开发工作,由于每次应用程序的复杂性,并且想要测试构建(通常),因此我必须将五个文件从构建二进制目录复制到安装二进制目录。这变得乏味。现在,我已经将文件名硬编码到了批处理脚本中,但是我想将它们放入数组中,以使脚本更易于维护。

我相信您正在寻找的是Makefile,也可能是cygwin,可以为您提供像样的外壳(bash,或您喜欢的任何口味)。


0

替换文本中的字符串和字母。

通过将文本扩展为for主体并用var替换var来尝试for循环。拖放文本文件,以便用户通过调用set命令输入%1。

@echo off
setlocal EnableDelayedExpansion
set /p a= enter letter to change:
set /p b= letter to change to:
set /p input=<%1
for /f %%c in ("!input:~!") do (
set "code=!input:%a%=%b%!"
echo !code!>myfile.txt
)

0

批处理文件中是这样的?在文件夹中选择一个文件。<<是注释,无代码

:selectapk
SETLOCAL ENABLEDELAYEDEXPANSION      << DELAYED EXPANSION on for counter in For loop
SET /A MAXITEM=0
Echo.
Echo Found these APK files in "add_apk_here" folder.
Echo.
For %%a in (add_apk_here/*.apk) do (
 Set /A MAXITEM+=1
 Set MENUITEM!MAXITEM!=%%a        << Fill n local env vars, one for each file, called MENUITEM1...n
 Echo    !MAXITEM!. %%a
)
Echo.
If !MAXITEM!==0 Echo No APK in "add_apk_here" folder & call :delay & Goto start   << No apk files then go back
SET /P CHOICE=Select APK to work on: 
SET MENUITEM=!MENUITEM%CHOICE%!      << Get the stored filename from MENUITEMx
SETLOCAL DISABLEDELAYEDEXPANSION     << Very important for next ENDLOCAL that doesn't like the delayedexpansion var
ENDLOCAL & SET apk=%MENUITEM%        << put the local MENUITEM var into the global apk var
goto start

:delay
REM %1 like Call :delay 5
SETLOCAL
SET N=%1
If Not Defined N Set N=2
Ping -n %N% -w 1000 127.255.255.255 > nul
ENDLOCAL
Exit /b

0

实际上不能在命令提示符下执行数组(而且除非您正在运行Windows 3.1,否则它并不是DOS)。但是,您可以使用FOR命令执行基于集合的处理

要创建要处理的文件列表,可以手动创建要处理的文本文件,或使用dir /b <mask>FOR循环中的命令。

我从FOR中学到了一些困难的方法-您需要使用SINGLE CHARACTER变量作为光标!


+1表示您应解释反对票。另外,您写了“您需要使用SINGLE CHARACTER变量作为光标!” <-您的意思是作为索引而不是光标
barlop 2014年

1
还要注意,如果它是DOS(DOS 7)的Win9X启动盘。Windows 9X仍然据说可以在DOS上运行。您可以添加一行到我认为是msdos.sys,例如bootscan = 0和bootgui = 0,这将阻止它启动进入Windows,并直接启动到DOS提示符。
barlop 2014年

0

查看有关FOR批处理命令的Microsoft文档。您可以使用FOR遍历一组目录,目录中的文件或目录中的文件及其所有子目录。

默认情况下,FOR处理集或仅处理文件:

FOR %f IN (*.txt) DO ECHO %f

或者,对于递归:

FOR /R %f IN (*.txt) DO ECHO %f

或者,仅对于目录:

FOR /D %d DO ECHO %d

不幸的是,所有这些选择都包含了各自的范围。我正在进行开发工作,由于每次应用程序的复杂性,并且想要测试构建(通常),因此我必须将五个文件从构建二进制目录复制到安装二进制目录。这变得乏味。现在,我已经将文件名硬编码到了批处理脚本中,但是我想将它们放入数组中,以使脚本更易于维护。
Jim Fell 2010年

0

这是一个很小的调试文件,我花了一段时间去BATCH / CMD中的井字游戏中测试阵列。它可以对数组进行读写操作,而对代码的处理又变得又复杂又复杂。

使用它很简单:

写入数组

  1. 给它一个文件或修改它以导入其他内容。
  2. 给数组起一个名字。
  3. 和你完成。

从数组读取

  1. 给出您想阅读的数组或数组的一部分的大小。
  2. 放入名称为%% a的阵列名称
  3. 和你完成。

码:

@echo off
setlocal EnableDelayedExpansion

set ID=0

::              Reader                   ::
:: It reads the file called input.txt    ::
:: and stores it in a new variable that  ::
:: for everytime it goes over it it is a ::
:: new ID (Slot in the array).           ::

For /F %%A in (input.txt) do ( 
    set /a ID=ID+1
    set Input!ID!= %%A

    echo !ID! : %%A
)


::             Writer                     ::
:: this is to read all Slots in the array ::
:: and puts it on the screen.             ::

for /L %%a in (1,1,!ID!) do (
    echo !Input%%a!
)
pause>nul
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.