Population Array in DOS Batch Script


33

Come posso impostare una variabile di array in uno script batch DOS? Vorrei caricarlo con un elenco di nomi di file da elaborare. Vorrei davvero renderlo il più semplice possibile. Grazie.


1
Devi davvero essere compatibile con DOS o puoi usare PowerShell?
Brian Knoblauch,

1
Puoi anche usare vbscript abbastanza facilmente per questo ...
JNK,

@Brian: è richiesto DOS. Scopri la soluzione che ho pubblicato.
Jim Fell,

Se non hai i capelli, dovresti sicuramente conoscere la differenza tra il prompt dei comandi e DOS
barlop

Risposte:


48

L'avevo capito:

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%

Ho fatto qualcosa del genere diversi anni fa, quindi ci sono voluti alcuni tentativi. (a proposito, odio reinventare la ruota.) Ora che è pubblicato qui, spero che anche altri lo troveranno utile.


1
Beh, non ho mai saputo che potresti farlo! Ho provato e funziona!
Linker3000,

Questo non può funzionare in DOS. DOS non fa nomi di file lunghi (solo 8.3) e, come ricordo, DOS non fa neanche citazioni nei percorsi dei file. Non ho un'installazione MS-DOS a portata di mano per vedere se supporta le matrici usando una ()sintassi.
un CVn

3
Mentre questo funziona per il tuo scopo, va notato che non è davvero un array. È solo una stringa che viene suddivisa in singoli elementi. Non puoi fare riferimento direttamente agli elementi facendo qualcosa di simile FILE_LIST[0].
aphoria,

@ MichaelKjörling: FreeDOS può supportare LFN e presumibilmente citazioni, quindi forse lo sta usando?
Nathan Tuggy,

@NathanTuggy Ottimo punto. Tuttavia, sarebbe meglio in tal caso se fosse reso esplicito.
un CVn il

12

Sì, puoi eseguire array in batch. Sebbene non siano esattamente come array in C o VB, puoi farlo:

@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
è fantastico e inspring .. ho appena fatto una risposta che si basa su questo e popola anche l'array
barlop

7

Dal blog di Jakash3, Array in Batch descrive come emulare gli array nel prompt dei comandi.

Un file batch denominato array.bat è incluso nell'articolo, che contiene una libreria di funzioni utilizzate per gestire le matrici. Dovrai selezionare il testo nell'articolo e incollarlo nel file bat.

Ad esempio, il seguente script di prova:

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

genera il seguente output:

Immagine


1
ok anche se non hai elencato il contenuto di array.bat anche se vedo che è un po 'lungo
barlop

4

Questo popola un array e lo stampa

Puoi usare names1 names2 names3, piuttosto che names [1] names [2] names [3] scrivendo names! I! invece dei nomi [! i!]. Produce l'array generando nomi di variabili. Non esiste una struttura di array in batch. Ma è pulito come qualsiasi struttura di array e il popolamento o la stampa assomigliano esattamente a come si popolerebbe o stamperebbe un array in un linguaggio corretto (che in realtà ha la struttura di array!)

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

L'output-

c:\blah>a
bob
tom
joseph

c:\blah>

Qualche spiegazione

Il setlocal enabledelayedexpansion enableextensionscon il! Var! anziché% var% è necessario per prevenire comportamenti strani, in modo che le variabili si comportino correttamente all'interno di un FOR o di un IF. È una stranezza con i file batch. Vedi set /?dove è menzionato ulteriormente.

Questo è ciò che popola l'array ed è piuttosto semplice per chiunque sia a conoscenza di array. Potresti anche fare anche names[0]=bob names[1]=tom names[2]=josephse una delle bellezze di un array è la possibilità di popolare un array con un loop, che è quello che ho fatto qui.

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

Questo visualizza l'array. %% f se lo fai eco, vedrai che passerà da 0 all'ultimo indice dell'array, con i passaggi di 1. quindi verranno stampati i nomi [0] nomi [1] nomi [2]

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

0

Per quello che vuoi fare, che ne dici di usare una variabile di input per ogni nome di file, che puoi prendere con le variabili% 1% 2 ecc. Ad esempio: mybat.bat file1.nam file2.nam ecc.

È quindi possibile utilizzare queste variabili in un ciclo, ma è necessario utilizzare solo% 1 come parametro principale in quanto è possibile utilizzare SHIFT per portare le altre variabili nella 'posizione'% 1, avendo un test per null (fine delle variabili) con qualcosa come IF "X% 1" == "X"

per esempio:

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

0

Se si salva l'elenco dei file in filelist.txt, è possibile FORleggere ed elaborare ciascuna riga del file, ad esempio

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

per stampare ogni riga di un file (fino al primo "|" nella riga. Se non si specifica il proprio delimitatore, verranno utilizzati lo spazio e la scheda, quindi a meno che i percorsi non abbiano spazi, è necessario specificare un carattere che non apparirà nel file per ottenere linee complete).


for / f è in realtà una funzionalità di Windows 2000 e successive. Non è in DOS.
wendy.krieger,

0

In uno dei tuoi commenti a una risposta dici,

Sto facendo un lavoro di sviluppo e, a causa della natura complessa dell'applicazione ogni volta e voglio testare una build (che spesso è) devo copiare cinque file dalla directory binaria build alla directory binaria di installazione. Questo diventa noioso. In questo momento, ho i nomi dei file hardcoded nel mio script batch, ma vorrei metterli in un array per rendere più semplice la manutenzione dello script.

Credo che quello che stai cercando sia un Makefile, e forse cygwin per darti un guscio decente (bash, o qualunque sia il tuo sapore).


0

Sostituisci stringhe e lettere nel testo.

Prova ad eseguire il ciclo espandendo il testo in a per il corpo e sostituendo var con var. Trascina e rilascia il file di testo in modo che% 1 sia l'input dell'utente invocando il comando 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
)

0

Qualcosa del genere in un file batch? Seleziona un file in una cartella. << è un commento, nessun codice

: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

Non è possibile eseguire realmente un array nel prompt dei comandi (e inoltre non è realmente DOS se non si esegue Windows 3.1). Tuttavia, è possibile eseguire l'elaborazione basata su set con il comando FOR.

Per creare l'elenco di file da elaborare, è possibile creare manualmente un file di testo da elaborare o utilizzare il dir /b <mask>comando all'interno del ciclo FOR.

Qualcosa che ho imparato a mie spese con FOR: devi usare una variabile SINGOLO PERSONAGGIO come cursore!


+1 si commenta che un downvote dovrebbe essere spiegato. Inoltre, hai scritto "devi usare una variabile SINGOLO PERSONAGGIO come cursore!" <- intendi come indice non come cursore
barlop

1
Si noti inoltre che se si tratta di un disco di avvio Win9X che è DOS (DOS 7). E si diceva ancora che Windows 9X funzionasse su DOS. E potresti aggiungere una linea a penso che fosse msdos.sys come bootscan = 0 e bootgui = 0 che avrebbe impedito l'avvio in Windows e l'avvio diretto a un prompt di DOS.
barlop,

0

Consulta la documentazione Microsoft sul comando batch FOR . È possibile utilizzare FOR per scorrere su un set di directory, file in una directory o file in una directory e tutte le sue sottodirectory.

Per impostazione predefinita, set di handle FOR o solo file:

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

Oppure, per ricorsivo:

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

o, solo per le directory:

FOR /D %d DO ECHO %d

Sfortunatamente, tutte queste opzioni sono all-inclusive per i rispettivi ambiti. Sto facendo un lavoro di sviluppo e, a causa della natura complessa dell'applicazione ogni volta e voglio testare una build (che è spesso) devo copiare cinque file dalla directory binaria build alla directory binaria di installazione. Questo diventa noioso. In questo momento, ho i nomi dei file hardcoded nel mio script batch, ma vorrei metterli in un array per rendere più semplice la manutenzione dello script.
Jim Fell,

0

questo è un piccolo file di debug che ho fatto un po 'di tempo per testare l'array dal mio gioco di rimorchio tic tac in BATCH / CMD. può leggere e scrivere da e verso un array senza andare troppo grande e complicato nel codice.

usarlo è semplice:

Scrivere in un array

  1. dagli un file o modificalo per importare qualcos'altro.
  2. dare un nome alla matrice.
  3. e hai fatto.

Lettura da un array

  1. Indica le dimensioni dell'array o parte di esso che desideri leggere.
  2. Inserisci il nome dell'array con %% a nel nome
  3. e hai fatto.

Codice:

@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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.