Заполнение массива в DOS Batch Script

33

Как я могу установить переменную массива в пакетном скрипте DOS? Я хотел бы загрузить его со списком имен файлов для обработки. Я действительно хотел бы сделать это как можно более простым. Спасибо.

Джим Фелл
источник
1
Вы действительно должны быть совместимы с DOS или можете использовать PowerShell?
Брайан Ноблаух
1
Вы также можете довольно легко использовать vbscript для этого ...
JNK
@Brian: DOS требуется. Проверьте решение, которое я отправил.
Джим Фелл
Если у вас нет волос, вы должны знать разницу между командной
строкой

Ответы:

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, чтобы увидеть, поддерживает ли она массивы с использованием ()синтаксиса.
CVn
3
Хотя это работает для вашей цели, следует отметить, что это не совсем массив. Это просто строка, которая разбивается на отдельные элементы. Вы не можете ссылаться на элементы напрямую, делая что-то вроде FILE_LIST[0].
афория
@ MichaelKjörling: FreeDOS может поддерживать LFN и предположительно кавычки, так что, может быть, он использует это?
Натан Тагги,
@NathanTuggy Хорошая мысль. Тем не менее, было бы лучше в этом случае, если бы это было сделано явно.
CVN
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
это удивительно и вдохновляюще ... я только что сделал ответ, который основывается на этом и также заполняет массив
barlop
7

В блоге Jakash3 Arrays in Batch описано, как эмулировать массивы в командной строке.

Пакетный файл с именем 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%.

генерирует следующий вывод:

образ

harrymc
источник
1
хорошо, хотя вы не перечислили содержимое array.bat, хотя я вижу, что это немного долго
barlop
4

Это заполняет массив и печатает его

Вы можете использовать names1 names2 names3, а не names [1] names [2] names [3], написав names! I! вместо имен [! 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% необходим для предотвращения нечетного поведения, чтобы переменные вели себя правильно, находясь внутри 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. так же будет печатать names [0] names [1] names [2]

for /L %%f in (0,1,!lastindex!) do ( 
  echo !names[%%f]!
)
barlop
источник
0

Что вы хотите сделать, как насчет использования входной переменной для каждого имени файла, которую вы можете выбрать с помощью переменных% 1% 2 и т. Д., Например: mybat.bat file1.nam file2.nam и т. Д.

Затем вы можете использовать эти переменные в цикле, но вам нужно только использовать% 1 в качестве основного параметра, так как вы можете использовать SHIFT, чтобы перевести другие переменные в% 1 «позицию», имея тест на ноль (конец переменных) с чем-то например, если "X% 1" == "X"

например:

:LOOP
IF "X%1" == "X" GOTO DONE
COPY %1 C:\TARGET.DIR
SHIFT
GOTO LOOP
:DONE
Linker3000
источник
0

Если вы сохраните список файлов в filelist.txt, вы сможете FORпрочитать и обработать каждую строку файла, например:

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

для печати каждой строки файла (до первого символа «|» в строке. Если вы не укажете свой собственный разделитель, будут использоваться пробел и табуляция, поэтому, если в ваших путях нет пробелов, вам нужно указать символ это не появится в файле, чтобы получить полные строки).

Нил
источник
for / f на самом деле является функцией Windows 2000 и более поздних версий. Это не в DOS.
wendy.krieger
0

В одном из ваших комментариев к ответу вы говорите:

Я занимаюсь разработкой, и из-за сложной природы приложения каждый раз и хочу протестировать сборку (что часто бывает), мне приходится копировать пять файлов из двоичного каталога сборки в установочный двоичный каталог. Это становится утомительным. Прямо сейчас у меня есть имена файлов, жестко запрограммированные в моем пакетном скрипте, но я бы хотел поместить их в массив, чтобы облегчить поддержку скрипта.

Я считаю, что вы ищете Makefile и, возможно, Cygwin, чтобы дать вам приличную оболочку (bash или любой другой ваш вкус).

lorenzog
источник
0

Заменить строки и буквы в тексте.

Попробуйте цикл, расширив текст до for и заменив var на var. Перетащите текстовый файл, чтобы% 1 был введен пользователем, вызвав команду set.

@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
)
mordex
источник
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
tweakradje
источник
0

Вы не можете действительно сделать массив в командной строке (а также это на самом деле не DOS , если вы не работаете в Windows 3.1). Однако вы можете выполнять обработку на основе множеств с помощью команды FOR.

Чтобы создать список файлов для обработки, вы можете вручную создать текстовый файл для обработки или использовать dir /b <mask>команду внутри цикла FOR.

Что-то, чему я научился с помощью FOR - вам нужно использовать переменную SINGLE CHARACTER в качестве курсора!

JNK
источник
+1 Вы комментируете, что отрицательный голос должен быть объяснен. Кроме того, вы написали «вам нужно использовать переменную SINGLE CHARACTER в качестве курсора!» <- ты имеешь в виду, что твой индекс не как твой курсор
barlop
1
Также обратите внимание, что если это загрузочный диск Win9X, то это DOS (DOS 7). А Windows 9X все еще говорили, что он работает на DOS. И вы можете добавить строку, я думаю, что msdos.sys, такой как bootscan = 0 и bootgui = 0, остановит загрузку в Windows и загрузит прямо в командной строке DOS.
Бароп
0

Ознакомьтесь с документацией Microsoft по пакетной команде FOR . Вы можете использовать FOR для перебора набора каталогов, файлов в каталоге или файлов в каталоге и всех его подкаталогах.

По умолчанию FOR обрабатывает набор или просто файлы:

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

Или для рекурсии:

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

или только для каталогов:

FOR /D %d DO ECHO %d
heavyd
источник
К сожалению, все эти варианты являются всеобъемлющими для соответствующих областей. Я занимаюсь разработкой, и из-за сложной природы приложения каждый раз и хочу протестировать сборку (что часто бывает), мне приходится копировать пять файлов из двоичного каталога сборки в установочный двоичный каталог. Это становится утомительным. Прямо сейчас у меня есть имена файлов, жестко запрограммированные в моем пакетном скрипте, но я бы хотел поместить их в массив, чтобы облегчить поддержку скрипта.
Джим Фелл
0

Это небольшой файл отладки, который я сделал, чтобы протестировать массив из моей игры Tic Tac Tow в 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
Elforax
источник