Batch scripting by Andrea Mantoni Ultima modifica: %%mtime(%d %B %Y) = Introduzione = Batch è il linguaggio di scripting più usato in ambiente Windows perché è l'unico disponibile in tutte le versioni del SO. Tuttavia Batch ha diverse limitazioni: - non è strutturato (no funzioni, no classi) - per simulare le funzioni usano i goto (come assembly) - aritmetica solo intera con "set /P" - typeless ... Esistono diverse alternative che non hanno queste limitazioni: - VBScript (.VBS and .VBE files) is supported by *WSH = Windows Script Host* (obsoleto) - PowerShell - Perl, PHP, Python (cross-platform) = Sintassi = sintassi di base: command /option1 /option2 ... arg1 arg2 ... commenti: REM single-line comment :: alternative single-line comment espansione variabili: %VARIABLE% escape char: ^ OSS.: richiesto solo per il piping invocazione altri batch|funzioni: call script arg1 arg2 ... echoing: REM disabilita l'echoing per un singolo comando @command REM disabilita l'echoing per tutti i comandi seguenti echo off REM abilita l'echoing per tutti i comandi seguenti echo off REM ritorna lo stato corrente dell'echoing echo NOTA: se lo script contiene dei caratteri ASCII estesi (lettere accentate, etc.) è necessario inserire all'inizio: REM West European Latin (extended ISO 8859-1) chcp 1252 REM Multilingual (Latin I) chcp 850 REM Unicode chcp 65001 REM ... http://ss64.com/nt/chcp.html = ECHO = ECHO è il comando più usato per stampare del testo sulla console. sintassi di base: echo text OSS.: aggiunge sempre una newline esempi: REM stampa una stringa costante + variabile (appending implicito) echo your path contains: %PATH% REM stampa su stderr invece che su stdout echo text 1>&2 REM print an empty line echo. REM print to console WITHOUT a trailing newline: echo|set /p=text %variable% = Environment variables = name default value %SystemDrive% C: %SystemRoot% C:\WINDOWS, C:\WINNT (%SystemDirectory% C:\WINDOWS\System32, C:\WINNT\System32) not in winxp %WinDir% C:\WINDOWS, C:\WINNT %ComSpec% C:\WINDOWS\system32\cmd.exe %ProgramFiles% "C:\Program Files" or "C:\Program Files (x86)" (64-bit OSes only: depends on whether the calling process is itself a 32bit process or 64bit process) %ProgramFiles(x86)% "C:\Program Files (x86)" (64-bit OSes only) %ProgramW6432% "C:\Program Files" (64-bit OSes only) %Temp% C:\DOCUME~1\Usr\LOCALS~1\Temp from C:\Documents and Settings\Usr\Local Settings\Temp %Tmp% %HOMEDRIVE% C: (The drive letter associated with the user's home directory) %HOMEPATH% \Documents and Settings\Guest (The path to the user's home directory (excluding drive)) %AppData% C:\Documents and Settings\Guest\Application Data %OS% Windows_NT (The operating system the user is running) %USERDOMAIN% (The name of the domain that contains the user's account) %USERNAME% (The user's name) %ERRORLEVEL% (~Unix program exit codes, usually 0=success !0=error) %RANDOM% (a random number between 0 and 32767) %TIME% %PROCESSOR_ARCHITECTURE% ... http://en.wikipedia.org/wiki/Environment_variable DOS-Linux corrispondence table: DOS Dev Linux Device Description ------------------------------------------ NUL /dev/null Send into nothingness CON stdin stdin from console PRN LPT1 /dev/lp0 First printer device ... COM1 /dev/ttyS0 Firsst serial port ... = STRING MANIPULATIONS = substrings extraction: %test:~0,5% Extract only the first 5 characters %test:~7,5% Skip 7 characters and then extract the next 5 %test:~7% Skip 7 characters and then extract everything else %test:~-7% Extract only the last 7 characters %test:~0,-7% Extract everything BUT the last 7 characters %test:~7,-5% Extract between 7 from the front and 5 from the end %test:~-7,5% Go back 7 from the end then extract 5 towards the end %test:~-7,-5% Extract between 7 from the end and 5 from the end = SET = usi: - senza opzioni: definisce la variabili (tutte typeless) - opzione "/A": esegue calcoli matematici (solo interi, NO FLOATS) e stampa l'output - opzione "/P": legge l'input dell'utente esempi: set COUNT=5 REM incrementa COUNT di 1 set /a COUNT = %COUNT% + 1 > NUL set /a CELSIUS = %KELVIN% / 10 - 273 REM read a variable from the user (requires enter for confirmation) SET /P VARIABLE=enter the value? alternativa per leggere l'input (non richiede enter per conferma) (not available in Win <=XP): CHOICE /C YN /M "question " IF errorlevel 1 echo you answered yes IF errorlevel 2 echo you answered not = IF = sintassi generale: IF ( command1 command2 ... ) ELSE ( command3 command4 ... ) N.B.: se "commandX" contiene delle parentesi devono essere escaped con "^" NOTA2: se si vogliono settare delle variabili nel bloccho if è necessario usare "enabledelayedexpansion" ed espandere le variabili con la sintassi "!VARIABILE!" testare l'esistenza di un file|dir: IF [NOT] EXIST filename command testare l'esistenza di una directory (no file): if exist "%~1\" ... source: http://stackoverflow.com/questions/138981/how-do-i-test-if-a-file-is-a-directory-in-a-batch-script/13600728#13600728 confronto stringhe: IF [/I] [NOT] item1==item2 command /I = case-insensitive comparison controllo se una variabile è definita: IF [NOT] DEFINED variable command verifica l'esistenza di un argomento: IF [%1]==[] ECHO Value Missing IF [%1]==[-h] ECHO first argument is "-h" confronto di variabili numeriche: IF (2) GEQ (15) echo "bigger" ^ | operatori di confronto: EQU : equal NEQ : not equal LSS : less than < LEQ : less than or equal <= GTR : greater than > GEQ : greater than or equal >= AND logico per realizzarlo, concatenare gli IF: IF IF OR logico per realizzarlo, trasformarlo in NOT+AND NOTA: se ci sono anche le clausole ELSE, è meglio usare le variabili temporanee: SET Result=0 IF %1 LSS 10 SET Result=1 IF %2 GTR 0 SET Result=1 IF %Result% EQU 1 ( ECHO %1 is less than 10 OR %2 is greater than 0 ) ELSE ( ECHO %1 is NOT less than 10 AND %2 is NOT greater than 0 ) test CPU architecture: IF PROCESSOR_ARCHITECTURE == x86 IF PROCESSOR_ARCHITEW6432 NOT DEFINED ( REM 32bit ) ELSE ( REM 64bit ) test CPU architecture (alternativo): if exist "%ProgramFiles(x86)%" ( REM 64bit ) else ( REM 32bit ) test windows version: source http://adamstech.wordpress.com/2009/07/16/use-a-batch-file-to-detect-windows-2k-xp-2003-vista-or-7/ SET OSVersion=Unknown REM 95, 98? ver | findstr "NT" > nul IF %ERRORLEVEL% EQU 0 SET OSVersion=NT VER | FINDSTR /L “5.0″ > NUL IF %ERRORLEVEL% EQU 0 SET OSVersion=2000 VER | FINDSTR /L “5.1.” > NUL IF %ERRORLEVEL% EQU 0 SET OSVersion=XP VER | FINDSTR /L “5.2.” > NUL IF %ERRORLEVEL% EQU 0 SET OSVersion=2003 VER | FINDSTR /L “6.0.” > NUL IF %ERRORLEVEL% EQU 0 SET OSVersion=Vista :: VER | FINDSTR /L “6.1.” > NUL :: IF %ERRORLEVEL% EQU 0 SET OSVersion=”7 Or Vista SP1 Or 2008″ WMIC Os get Caption | FINDSTR “Vista” > NUL IF %ERRORLEVEL% EQU 0 SET OSVersion=Vista-SP1 WMIC Os get Caption | FINDSTR “7″ > NUL IF %ERRORLEVEL% EQU 0 SET OSVersion=7 WMIC Os get Caption | FINDSTR “2008″ > NUL IF %ERRORLEVEL% EQU 0 SET OSVersion=2008 VER | FINDSTR /L “6.2.” > NUL IF %ERRORLEVEL% EQU 0 SET OSVersion=8 test windows version (alternativo): if exist "%SYSTEMDRIVE%\Users" ( REM vista and win 7 ) else ( REM WinXP ) = FOR = Il comando FOR si presta a diversi utilizzi: - SENZA OPZIONI: itera in una lista (gli spazi sono i separatori): FOR %%C IN (blue red yellow white) DO echo %%C - OPZIONE /L: itera in una sequenza di numeri: for /L %%N in (start, step, end) do echo %%N - OPZIONE /F: itera su un insieme di files: FOR /F "" %%F IN (*.txt) DO echo %%F NOTA: problemi se i files contengono spazi, usare invece FOR /F "delims=" %%F IN ('dir /b *.ext') DO ... - OPZIONE /F: itera sull'output di un comando: FOR /F ["options"] %%parameter IN ('command_to_process') DO command - OPZIONE /F: itera su le righe di un file FOR /F "" %%G IN (weather.txt) DO echo %%G - OPZIONE /R: itera su un insieme di files + recurse sub-dirs: FOR /R [[drive:]path] %%parameter IN (set) DO command esempio: REM cicla un insieme di files ed estrae il filename setlocal EnableDelayedExpansion for /f "delims=" %%G in ('dir /b *.ext') do ( set file=%%G REM set filename=%file:.*=% set filename=!file:~0,-4! echo !filename! :: comment command1 %%G command2 %%G :: comment command3 %%G ) MEMO: l'ultimo comando nn può essere 1 commento = GOTO+LABEL= sintassi: REM ... GOTO label_name REM ... :label_name REM ... etichette builtin: :eof = End Of File -> esce dallo script = Funzioni = definizione: ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :MonthName %mm% month :: :: By: Ritchie Lawrence, 2002-10-04. Version 1.0 :: :: Func: Returns the name of month from the number of the month. :: For NT4/2K/XP :: :: Args: %1 month number convert to name of month, 1 or 01 to 12 (by val) :: %2 var to receive name of month (by ref) ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: setlocal ENABLEEXTENSIONS&set /a m=100%1%%100 for /f "tokens=%m%" %%a in ('echo/January February March April May June^ July August September October November December' ) do endlocal&set %2=%%a&goto :EOF ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: invocazione: set month=06 call :MonthName %month% monthname = Parametri = Possono essere letti sia dal batch principale, sia nelle funzioni: %* - all the arguments %0 - the Batch Script itself %1 - first item passed %2 - second item passed ... %9 %~1 - expand %1 removing any surrounding quotes (") %~f1 - expand %1 to a Fully qualified path name, eg.: "C:\utils\MyFile.txt" %~d1 - expand %1 to a Drive letter only, eg.: "C:" %~p1 - expand %1 to a Path only, eg.: ""\utils\" %~n1 - expand %1 to a file Name, or if only a path is present (with no trailing backslash\) - the last folder in that path %~x1 - expand %1 to a file eXtension only, eg.: ".txt" (NOTE: if double ext. returns the last one only) %~a1 - expand to the file attributes of %1, eg.: "" %~t1 - expand to the date/time of %1, eg.: "" %~z1 - expand to the file size of %1, eg.: "" %~s1 - change the meaning of f, n and x to reference the Short name (see note below) %~$PATH:1 - search the PATH environment variable and expand %1 to the fully qualified name of the first match found. Per leggere gli args >%9 bisogna necessariamente usare il comando "shift" N.B.: non può essere usato all'interno di blocchi IF, usare goto+label se necessario = Fonti = - http://ss64.com/nt/ - http://www.commandwindows.com/ - http://blog.crankybit.com/why-that-batch-for-loop-isnt-working/