Array im DOS-Batch-Skript auffüllen


33

Wie kann ich eine Array-Variable in einem DOS-Batch-Skript einrichten? Ich möchte es mit einer Liste der zu verarbeitenden Dateinamen laden. Ich möchte das wirklich so einfach wie möglich halten. Vielen Dank.


1
Müssen Sie wirklich DOS-kompatibel sein oder können Sie PowerShell verwenden?
Brian Knoblauch

1
Sie können auch VBScript ziemlich einfach für diese verwenden ...
JNK

@ Brian: DOS ist erforderlich. Schauen Sie sich die Lösung an, die ich gepostet habe.
Jim Fell

Wenn Sie keine Haare haben, sollten Sie den Unterschied zwischen der Eingabeaufforderung und DOS
barlop 29.08.14

Antworten:


48

Ich habe es herausgefunden:

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%

Ich habe so etwas vor einigen Jahren gemacht, also musste ich es erst herausfinden. (Übrigens hasse ich es, das Rad neu zu erfinden.) Jetzt, da es hier veröffentlicht ist, werden es hoffentlich auch andere nützlich finden.


1
Ich hätte nie gedacht, dass du das kannst! Ich habe es versucht und es funktioniert!
Linker3000

Dies kann unmöglich unter DOS funktionieren. DOS macht keine langen Dateinamen (nur 8.3), und wie ich mich erinnere, macht DOS auch keine Anführungszeichen in Dateipfaden. Ich habe keine MS-DOS-Installation zur Hand, um festzustellen, ob Arrays mithilfe einer ()Syntax unterstützt werden.
ein Lebenslauf

3
Dies funktioniert zwar für Ihren Zweck, es sollte jedoch beachtet werden, dass es sich nicht wirklich um ein Array handelt. Es ist nur eine Zeichenfolge, die in einzelne Elemente aufgeteilt wird. Sie können die Elemente nicht direkt referenzieren, indem Sie so etwas tun FILE_LIST[0].
Aphoria

@ MichaelKjörling: FreeDOS kann LFNs und vermutlich auch Zitate unterstützen, vielleicht nutzt er das also?
Nathan Tuggy

@ NathanTuggy Guter Punkt. Trotzdem wäre es in diesem Fall besser, wenn es explizit gemacht würde.
ein Lebenslauf vom

12

Ja, Sie können Arrays im Batch erstellen. Obwohl sie nicht wie Arrays in C oder VB sind, können Sie dies tun:

@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
das ist fantastisch und sprunghaft. ich habe gerade eine antwort gemacht, die darauf aufbaut und auch das array
auffüllt

7

In Jakash3s Blog beschreibt Arrays in Batch , wie Arrays in der Eingabeaufforderung emuliert werden.

In dem Artikel ist eine Batchdatei mit dem Namen array.bat enthalten, die eine Bibliothek mit Funktionen zum Verarbeiten von Arrays enthält. Sie müssen den Text im Artikel auswählen und in die bat-Datei einfügen.

Zum Beispiel das folgende Testskript:

@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%.

erzeugt die folgende Ausgabe:

Bild


1
ok, obwohl Sie den Inhalt von array.bat nicht aufgelistet haben, obwohl ich sehe, dass es ein bisschen lang ist
Barlop

4

Dies füllt ein Array und druckt es

Sie könnten anstelle von names [1] names [2] names [3] names1 names2 names3 verwenden, indem Sie names! I! anstelle von Namen [! i!]. Es erzeugt das Array durch Generieren von Variablennamen. Im Batch gibt es keine Array-Struktur. Aber es ist so ordentlich wie jede Array-Struktur, und das Auffüllen oder Drucken sieht genauso aus wie das Auffüllen oder Drucken eines Arrays in einer geeigneten Sprache (die tatsächlich die Array-Struktur hat!).

@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]!
)

die Ausgabe-

c:\blah>a
bob
tom
joseph

c:\blah>

Einige Erklärungen

Das setlocal enabledelayedexpansion enableextensionsmit dem! Var! Statt% var% ist erforderlich, um ungewöhnliches Verhalten zu verhindern, damit sich Variablen innerhalb eines FOR oder eines IF ordnungsgemäß verhalten. Es ist eine Kuriosität mit Batch-Dateien. Sehenset /? wo das weiter erwähnt wird.

Dies ist es, was das Array ausfüllt und ist für jeden, der sich mit Arrays auskennt, ziemlich einfach. Sie könnten es auch tun, names[0]=bob names[1]=tom names[2]=josephobwohl eine der Schönheiten eines Arrays die Fähigkeit ist, ein Array mit einer Schleife zu füllen, was ich hier getan habe.

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

Dies zeigt das Array an. %% f, wenn Sie es wiederholen, werden Sie in Schritten von 1 von 0 bis zum letzten Index des Arrays gehen. So werden Namen [0] Namen [1] Namen [2] gedruckt

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

0

Was Sie tun möchten, ist die Verwendung einer Eingabevariable für jeden Dateinamen, die Sie mit den Variablen% 1% 2 usw. abrufen können, z. B .: mybat.bat file1.nam file2.nam etc ..

Sie können diese Variablen dann in einer Schleife verwenden, müssen jedoch nur% 1 als Hauptparameter verwenden, da Sie mit UMSCHALT die anderen Variablen an die 'Position' von% 1 bringen können, wobei ein Test auf Null (Ende von Variablen) mit etwas ausgeführt wird wie WENN "X% 1" == "X"

z.B:

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

0

Wenn Sie die Dateiliste FORin der Datei filelist.txt speichern, können Sie jede Zeile der Datei lesen und verarbeiten, z

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

Um jede Zeile einer Datei zu drucken (bis zum ersten "|" in der Zeile. Wenn Sie kein eigenes Trennzeichen angeben, werden Leerzeichen und Tabulatoren verwendet. Wenn Ihre Pfade also keine Leerzeichen enthalten, müssen Sie ein Zeichen angeben das wird nicht in der Datei angezeigt, um vollständige Zeilen zu erhalten).


Für / f ist eigentlich ein Windows 2000 und höher-Feature. Es ist nicht in DOS.
wendy.krieger

0

In einem Ihrer Kommentare zu einer Antwort sagen Sie:

Ich mache gerade Entwicklungsarbeiten, und aufgrund der Komplexität der Anwendung muss ich jedes Mal fünf Dateien aus dem Build-Binärverzeichnis in das Installations-Binärverzeichnis kopieren, um einen Build zu testen (was häufig der Fall ist). Das wird mühsam. Derzeit sind die Dateinamen in meinem Stapelskript fest codiert, ich möchte sie jedoch in ein Array einfügen, um die Wartung des Skripts zu vereinfachen.

Ich glaube, was Sie suchen, ist ein Makefile und möglicherweise Cygwin, um Ihnen eine anständige Shell (bash oder was auch immer Ihr Geschmack) zu geben.


0

Ersetzen Sie Zeichenfolgen und Buchstaben im Text.

Versuchen Sie es mit einer for-Schleife, indem Sie den Text zu a for body erweitern und var durch var ersetzen. Ziehen Sie die Textdatei, und legen Sie sie ab, sodass% 1 eine Benutzereingabe ist, indem Sie den Befehl set aufrufen.

@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

So etwas in einer Batch-Datei? Wählen Sie eine Datei in einem Ordner. << ist Kommentar, kein Code

: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

Sie können nicht wirklich ein Array in der Eingabeaufforderung (und es ist auch nicht wirklich DOS, wenn Sie Windows 3.1 ausführen). Mit dem Befehl FOR können Sie jedoch eine satzbasierte Verarbeitung durchführen .

Um die Liste der zu verarbeitenden Dateien zu erstellen, können Sie manuell eine zu verarbeitende Textdatei erstellen oder den dir /b <mask>Befehl in der FOR-Schleife verwenden.

Etwas, das ich auf die harte Tour mit FOR gelernt habe - Sie müssen eine SINGLE CHARACTER- Variable als Cursor verwenden!


+1 Sie kommentieren, dass eine Ablehnung erklärt werden sollte. Außerdem haben Sie geschrieben: "Sie müssen eine SINGLE CHARACTER-Variable als Cursor verwenden!" <- Sie meinen als Ihr Index nicht als Ihr Cursor
Barlop

1
Beachten Sie auch, dass DOS (DOS 7) ist, wenn es sich um eine Win9X-Startdiskette handelt. Und Windows 9X lief angeblich immer noch unter DOS. Und Sie könnten eine Zeile hinzufügen, wenn Sie der Meinung sind, dass es msdos.sys wie bootscan = 0 und bootgui = 0 ist, die den Start von Windows stoppen und direkt zu einer DOS-Eingabeaufforderung starten.
Barlop

0

Lesen Sie die Microsoft-Dokumentation zum Befehl FOR batch . Mit FOR können Sie eine Reihe von Verzeichnissen, Dateien in einem Verzeichnis oder Dateien in einem Verzeichnis und all seinen Unterverzeichnissen durchlaufen.

Standardmäßig werden FOR-Handles gesetzt oder nur Dateien:

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

Oder für rekursive:

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

oder nur für Verzeichnisse:

FOR /D %d DO ECHO %d

Leider sind alle diese Optionen für ihren jeweiligen Anwendungsbereich allumfassend. Ich mache gerade Entwicklungsarbeiten, und aufgrund der Komplexität der Anwendung muss ich jedes Mal fünf Dateien aus dem Build-Binärverzeichnis in das Installations-Binärverzeichnis kopieren, um einen Build zu testen (was häufig der Fall ist). Das wird mühsam. Derzeit sind die Dateinamen in meinem Stapelskript fest codiert, ich möchte sie jedoch in ein Array einfügen, um die Wartung des Skripts zu vereinfachen.
Jim Fell

0

Dies ist eine kleine Debug-Datei, die ich vor einiger Zeit erstellt habe, um das Array aus meinem Tic Tac Tow-Spiel in BATCH / CMD zu testen. Es kann in und aus einem Array lesen und schreiben, ohne dass der Code zu groß und zu kompliziert wird.

es zu benutzen ist einfach:

In ein Array schreiben

  1. gib ihm eine Datei oder ändere sie, um etwas anderes zu importieren.
  2. Geben Sie dem Array einen Namen.
  3. und du bist fertig.

Aus einem Array lesen

  1. Geben Sie die Größe des Arrays oder eines Teils davon an, den Sie lesen möchten.
  2. Geben Sie den Namen des Arrays mit %% a im Namen ein
  3. und du bist fertig.

Code:

@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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.