Comandos Batch en Windows

Embed Size (px)

Citation preview

  • Archivos por lotes (batch)

    Los tipos de fichero que puede ejecutar MS-DOS desde lnea de comandos deben tener la extensin .exe, .com o .bat. Los dos primeros son archivos en lenguaje mquina (compilados), el tercero es un fichero ASCII, cuyas lneas son comandos MS-DOS que sern interpretados por la shell.

    Para llamarlos basta con escribir su nombre en la lnea de comandos, no es necesario especificar la extensin, pero deben estar accesibles: bien en el directorio actual ( . ), o bien en alguno de los directorios especificados en la variable PATH.

    Qu sucede si dos archivos ejecutables se denominan igual?, los ficheros bat son los que tienen menor prioridad de ejecucin: 1) macros 2) comandos internos 3) .exe 4) .com 5) .bat

    Ejemplo. El siguiente archivo bat crea una unidad virtual Z: para el directorio en que nos encontramos:

    uvz.bat subst Z: . C:\Documents and Settings\Administrador>copy con uvz.bat subst Z: . ^Z 1 archivos copiados. C:\Documents and Settings\Administradoruebas>uvz ejecuto el archivo bat C:\Documents and Settings\Administrador>subst Z: . me muestra el comando que va a ejecutar C:\Documents and Settings\Administradorebas>z: Z:\>subst Z:\: => C:\Documents and Settings\Administrador

    Puede contener mltiples lneas:

    uvz.bat

    subst /d Z: subst Z: . subst

    comentarios

  • En un archivo por lotes podemos incluir lneas de comentario con la palabra REM (remark):

    REM comentario

    Comando ECHO

    Nos permite visualizar mensajes en pantalla.

    ECHO [mensaje | ON | OFF] Muestra mensajes o activa y desactiva el eco del comando. Escriba ECHO sin parmetros para mostrar la configuracin actual del eco.

    echo. inserta una lnea en blanco

    El siguiente bat muestra un listado simple de directorio, separando archivos de directorios:

    REM list.bat echo --- ARCHIVOS --- dir /a-d /b /on echo --- DIRECTORIOS --- dir /ad /b /on

    Eco de los comandos

    Cada comando de un archivo por lotes es visualizado en pantalla antes de ser ejecutado. Esto puede estar bien para depuracin, pero a veces es un poco molesto:

    La ejecucin del fichero bat anterior (list.bat) sera:

    C:\Documents and Settings\Administrador>list C:\Documents and Settings\Administrador>REM list.bat echo --- ARCHIVOS --- dir /a-d /b /on echo --- DIRECTORIOS --- dir /ad /b /on

  • Pero si deseamos anular el eco para todos los comandos, la primera lnea ser el comando ECHO OFF:

    @echo off REM list.bat echo --- ARCHIVOS --- dir /a-d /b /on echo --- DIRECTORIOS --- dir /ad /b /on

    Ahora la ejecucin del fichero bat es la siguiente:

    C:\Documents and Settings\Administrador>list --- ARCHIVOS --- ntuser.bak ntuser.dat NtUser.dat.LOG ntuser.ini --- DIRECTORIOS --- Escritorio Favoritos Men Inicio Mis documentos

    Estructura de bifurcacin GOTO

    En un archivo bat la ejecucin de los comandos no es necesariamente secuencial, la intruccin GOTO nos permite continuar la ejecucin del archivo BAT en otro punto del mismo:

    GOTO etiqueta -comandos- :etiqueta -comandos-

    El siguiente archivo zzz.bat muestra de manera indefinida los segundos pasar:

    @echo off set cont=0 :bucle cls echo Mira pasar el tiempo ... %cont% ping -n 1 -w 800 0.0.0.1 > NUL set /a cont=cont+1 goto bucle

    Para la mayora de los comandos, cuando no pueden ejecutarse por algn motivo, se muestra el mensaje de error correspondiente y contina la ejecucin con el siguiente de la lista. En el caso del GOTO (y unos pocos ms), si no existiera la etiqueta 'bucle' finalizara el programa con un error.

  • Su uso principal es en las estructuras if.

    Pausar el programa

    A veces interesar suspender temporalmente la ejecucin de un archivo bat para que el usuario lleve a cabo alguna accin: encender la impresora, insertar cierto disquete, interrumpir el proceso, ...

    PAUSE

    Suspende el proceso de un programa por lotes y por muestra el mensaje Presione una tecla para continuar...

    Ejemplos:

    @ECHO OFF CLS ECHO Inserte el diskette de nminas en la unidad A: PAUSE ... @ECHO Se van a borrar todos los archivos de la unidad Z: @ECHO Ctrl + C para interrumpir @PAUSE ...

    Carcter de escape en MS-DOS

    Cuando deseamos permutar el significado de alguno de los caracteres con significado especial (pipe, operadoress de redireccin, ...) le precederemos del smbolo ^ (ALT + 94).

    El siguiente programa BAT no funcionara como se espera, pues interpreta el pipe como "redireccin a entrada estndar del comando /?":

    ayuda.bat

    @echo off echo Sintaxis: echo reboot [ hh:mm | /? ] X:\>ayuda Sintaxis: "/?" no se reconoce como un comando interno o externo, programa o archivo por lotes ejecutable.

    La solucin sera:

    echo reboot [ hh:mm ^| /? ]

    Tambin sera til en un caso como el siguiente:

    echo ^ > pagweb.html

  • para evitar que la shell interprete cierto smbolos mayor/menor como operadores de redireccionamiento.

    Paso de parmetros a un archivo bat Hay dos mtodos para pasar informacin:

    1) lnea de comandos 2) entrada estndar

    1- Paso de parmetros a un archivo bat desde entrada estndar

    SET /P variable=[mensaje] El modificador /P permite establecer el valor de una variable para una lnea de entrada escrita por el usuario. Muestra el mensaje antes de leer la lnea de entrada. NOTA: Funciona a partir de W2000, y deben estar habilitadas las extensiones de comando. grosero.bat

    @echo off set /p nombre=Cmo te llamas? echo. echo nunca me gust el nombre de %nombrex%

    Por recibir el argumento desde entrada estndar, podemos introducir la informacin a travs de de un pipe, o redirigida desde un archivo o dispositivo:

    X:\pruebas>grosero.bat Cmo te llamas? Paco Pico nunca me gust el nombre de Paco Pico X:\pruebas>echo Ferreolo Anastasio | grosero.bat Cmo te llamas? nunca me gust el nombre de Ferreolo Anastasio X:\pruebas>grosero.bat < grosero.bat Cmo te llamas? nunca me gust el nombre de @echo off

    NOTA: Podemos usar comillas en el mensaje que no sern visualizadas: set /p nombre="Cmo te llamas? "

    2- Paso de parmetros a un archivo bat desde lnea de comandos

    Podemos introducir datos al fichero .bat desde lnea de comandos, que sern almacenados en las denominadas variables posicionales:

    %0, %1, %2, ..., %9 En %0 se almacena el nombre del comando En %1 se guarda el valor del primer argumento

  • En %2 se guarda el valor del segundo argumento, y as sucesivamente.

    El parmetro %* contiene la lista con todos los argumentos introducidos desde lnea de comandos.

    El siguiente programa repite lo que introducimos desde lnea de comandos (excepto el nombre del comando): repite.bat

    @echo %*

    Y sin mucho esfuerzo podemos dar la vuelta a una frase de hasta 9 palabras:

    reverse.bat

    @echo %9 %8 %7 %6 %5 %4 %3 %2 %1 X:\>repite lo que yo te diga lo que yo te diga X:\>reverse lo que yo te diga diga te yo que lo

    SHIFT

    En el ejemplo anterior, vemos que si la frase tiene ms de 9 palabras, reverse no las visualiza:

    X:\>reverse En un lugar de la mancha cuyo nombre no quiero acordarme nombre cuyo de Mancha la de lugar En

    Cuando los argumentos desde lnea de comandos son ms de 9, es necesario irlos desplazando si queremos leer todos. El comando SHIFT desplaza el valor de todos los argumentos posicionales un lugar hacia la izquierda:

    modifiquemos un poco el fichero reverse.bat para ver el funcionamiento de shift:

    reverse.bat

    @echo off

  • echo %9 %8 %7 %6 %5 %4 %3 %2 %1 shift echo %9 %8 %7 %6 %5 %4 %3 %2 %1 shift echo %9 %8 %7 %6 %5 %4 %3 %2 %1 X:\> en un lugar de la mancha cuyo nombre no quiero acordarme nombre cuyo de Mancha la de lugar un En no no nombre cuyo de Mancha la de lugar un quiero quiero no nombre cuyo de Mancha la de lugar

    Si las extensiones de comando estn habilitadas, podemos comenzar los deplazamientos en un determinado parmetro. Por ejemplo:

    SHIFT /2 Realiza el desplazamiento a partir del argumento %2, dejando fijos los parmetros %0 y %1

    Estructura de control: IF

    Mediante la estructura IF podemos realizar un procesamiento condicional en programas por lotes.

    IF [NOT] {cadena1==cadena2 | EXIST archivo | ERRORLEVEL nmero} comando cadena1==cadena2 - La condicin es verdadera si las cadenas de texto son exactamente iguales (comparacin de cadenas case sensitive). EXIST archivo - Es verdadero si existe el archivo especificado. ERRORLEVEL nmero - La condicin es verdadera si la ejecucin del ltimo comando devolvi un cdigo de salida igual o mayor (>=) que el nmero especificado. comando - es el comando que se ejecutar si se cumple la condicin. NOT - Niega la condicin: el comando se ejecutar si la condicin es falsa.

    Cuando no estemos muy seguros de que los operandos del IF vayan a contener algn valor, conviene aadir algn delimitador con el fin de evitar comparaciones con un "vaco". Las siguientes lneas provocarn un error cuando el usuario no introduzca ningn valor en la variable posicional %1:

    IF %1==TE goto TERUEL IF NOT EXIST %1 echo NO ENCUENTRO EL ARCHIVO

    pues la comparacin a realizar sera:

    IF ==TE goto TERUEL

  • IF "%1"=="TE" goto TERUEL IF {%1}=={TE} goto TERUEL IF .%1==.TE goto TERUEL IF gamusino%1verde==gamusinoTEverde goto TERUEL IF NOT EXIST "%1" echo NO ENCUENTRO EL ARCHIVO

    OR

    No existe el operador OR, la alternativa es ejecutar varias IF una a continuacin de otra:

    if "%1"=="/?" goto AYUDA if "%1"=="--help" goto AYUDA if "%1"=="" goto AYUDA

    AND

    Para el operador AND debemos anidar IF:

    IF EXIST "%1" IF EXIST "%2" COMP %1 %2

    EJEMPLOS

    En el siguiente ejemplo se ha aadido una ayuda al comando repite.bat:

    @echo off if "%1"=="/?" goto AYUDA if "%1"=="" goto FIN echo %* goto FIN :AYUDA echo. echo Este comando repite la frase que usted escriba echo - Sintaxis: echo repite [ /? ^| frase] echo. :FIN

    El siguiente programa aade la hora actual al archivo introducido desde lnea de comandos, si no existe nos informa del fallo:

    @echo off if NOT EXIST "%1" goto ERROR echo %TIME% >> %1 goto FIN :ERROR echo No se encontr el fichero %1 :FIN

  • Qu sucede si %1 es un directorio?

    ERRORLEVEL

    Casi todos los comandos, tras su ejecucin, devuelven un cdigo de estado, que es un nmero indicativo de cmo ha finalizado la ejecucin del programa. Este cdigo suele ser 0 cuando la ejecucin finaliz con xito, y otro valor si hubo algn tipo de anomala.

    Cuando el comando IF compara el errorlevel, nos devolver 'true' cuando este sea superior o igual al nmero especificado. Es decir: IF ERRORLEVEL 3 comando equivaldra a: si (errorlevel >= 3) comando IF NOT ERRORLEVEL 3 comando equivaldra a: si (errorlevel < 3) comando

    Los siguientes fragmentos de cdigo tienen el mismo efecto:

    1) IF ERRORLEVEL 1 goto ALGUN_ERROR - comandos cuando errorlevel=1 - 2) IF NOT ERRORLEVEL 1 goto CORRECTO - comandos cuando errorlevel>=1 - :CORRECTO - comandos cuando errorlevelNUL 2>NUL if errorlevel 1 goto NO-DISCO REM aqu iran las operaciones a realizar sobre el diskete goto FIN :NO-DISCO echo Introduzca un disquete en la unidad A: pause goto LEER :FIN

    NOTA: Podramos haber utilizado DIR, aunque si el directorio raz est vaco tambin devuelve un errorlevel igual a 1.

    ejercicios. 1. El siguiente programa en ensamblador lee una pulsacin de teclado y almacena su cdigo ASCII en la variable ERRORLEVEL:

  • Z:\>debug getch.com No se encuentra el archivo -a 1517:0100 mov ah, 08 - funcin que captura la pulsacin de una tecla sin eco, 1517:0102 int 21 almacena el resultado en AL 1517:0104 mov ah, 4C - funcin que retorna al programa llamante, con cdigo de 15A6:0106 int 21 retorno el almacenado en AL 15A6:0108 -r cx CX 0008 :8 -w Escribiendo 00008 bytes -q Z:\>getch - aqu pulso la X mayscula - Z:\>echo %errorlevel% 88

    Completar el siguiente archivo BAT que muestra un men con varias opciones:

    @echo off :MENU cls echo elija opcin echo A-Archivo de clientes echo B-Archivo de proveedores echo C-Finalizar getch if errorlevel ..?.. goto CLIENTES, PROVEEDORES o FIN ..?.. if errorlevel ..?.. goto CLIENTES, PROVEEDORES o FIN ..?.. if errorlevel ..?.. ... ..?.. goto MENU :CLIENTES ... :PROVEEDORES ... :FIN

    Cdigos ASCII: A (65), B (66), C (67), a (97), b (98), c (99)

    2. Escribir un programa ping2.bat que nos permite hacer un ping a mltiples hosts de una misma red. Nos mostrar un mensaje diciendo si el host est o no conectado:

  • C:\>ping2 13 2 5 55 99 128 129 130 131 132 133 200 201 222 192.168.1.13 - conectado 192.168.1.2 - conectado 192.168.1.5 - NO EST CONECTADO 192.168.1.55 - conectado ...

    INDICACIN: Cuando se hace ping a una IP, el errorlevel devuelto siempre es 0, independientemente de que nos respondan con un pong. Para discernir entre un host conectado y uno inalcanzable, debemos generar un errorlevel, por ejemplo buscando con FIND alguna palabra en la informacin mostrada por el PING, que ser distinta en cada caso.

    2. Mejorar el programa anterior, de manera que el primer argumento sea la red:

    C:\>ping3 10.0.0 13 2 5 55 99 128 129 130 131 132 133 200 201 222 10.0.0.13 - conectado 10.0.0.2 - conectado 10.0.0.5 - NO EST CONECTADO 10.0.0.55 - conectado ...

    MEJORAS en el IF

    Cuando las extensiones de comando estn habilitadas, IF tiene mayor funcionalidad:

    a) Podemos preguntar por la existencia de variables:

    IF DEFINED variable comando C:\sirio>set x=25 C:\sirio>if defined x echo Ya existe la variable x, su valor es %x% Ya existe la variable x, su valor es 25

    b) Y realizar comparaciones lgicas, diferentes a la igualdad:

    IF [/I] cadena1 op-log cadena2 comando Los operadores lgicos admitidos son: EQU - igual NEQ - no igual LSS - menor que LEQ - menor que o igual GTR - mayor que GEQ - mayor que o igual /I indica que la comparacin se har case insensitive (ignora la diferencia entre MAYs y mins)

    c) Ahora el IF admite ms de un comando, el grupo de comandos debemos encerrarlo entre parntesis. Tambin admite la clusula (opcional) ELSE:

    IF expr-lgica ( - sentenciaS TRUE - ) ELSE (

  • - sentenciaS FALSE - ) C:\>set a=Andorra C:\>set b=Barcelona C:\>IF a LSS b (echo %a% %b%) ELSE (echo %b% %a%) Andorra Barcelona

    Expansin retardada de variables

    Las variables comprendidas entre los parntesis las expande en el momento de la llegada al IF: antes de ejecutar ninguna de las instrucciones interiores.

    En el siguiente programa:

    @echo off set VAR=basura echo antes del IF: %VAR% IF DEFINED VAR ( set VAR=CHATARRA echo en el IF: %VAR% ) echo despus del IF: %VAR%

    su ejecucin nos dara un resultado un tanto sorprendente:

    C:\prueba>prog antes del IF: basura en el IF: basura Pero si ya he cambiado el valor de la variable !! despus del IF: CHATARRA

    La solucin a este problema es utilizar lo que en palabras de soft se conoce como "expansin de variables retardada" (ver cmd /? y set /?): 1. Debemos habilitarla (por defecto vienen deshabilitadas), para ello necesitamos abrir una subshell: cmd /v:on o bien introducir como primera instruccin del bat: SETLOCAL ENABLEDELAYEDEXPANSION

    2. Las variables que deseemos que se expandan en el momento preciso de su utilizacin las rodearemos con admiraciones (!).

    El siguiente programa funcionara correctamente:

    @echo off set VAR=basura echo antes del IF: %VAR% IF DEFINED VAR ( set VAR=CHATARRA echo en el IF (1): %VAR%

  • echo en el IF (2): !VAR! ) echo despus del IF: %VAR% C:\Documents and Settings\sirio\prueba>cmd /v:on Microsoft Windows 2000 [Versin 5.00.2195] (C) Copyright 1985-2000 Microsoft Corp. C:\Documents and Settings\sirio\prueba>vprog antes del IF: basura en el IF (1): basura repite ms-dos es "bueno, bonito y barato" ms-dos es "bueno, bonito y barato"

  • NOTA: Si las extensiones de comandos estn habilitadas, podemos suprimir las comillas de una variable con el smbolo ~ : for %%X in (%*) do echo %%~X (ms informacin: for /?)

    ejemplo 2

    Cuando aparece un * en la lista, lo interpreta como un comodn, y antes de aplicar el comando se crear una lista de archivos que cumpla con la expresin regular. En la elaboracin de la lista slo utiliza archivos, NO directorios.

    C:\pruebas>FOR %f IN (*) DO @echo %f for %f in (*.png, *.jpg, *.gif) do move %f C:\Recycled

    En el ltimo ejemplo hemos movido las imgenes con formatos grficos de internet a la papelera del disco C:. - Echar un vistazo a la papelera desde Windows se ven? Y desde MS-DOS? - Vaciar la papelera desde Windows. Se han borrado? - Volver al da siguiente y comprobar que las imgenes siguen ah: aunque tiremos de la cadena 1000 veces, los documentos nunca desaparecern. Una curiosa forma de esconder documentos y que nadie los borre: en la basura.

    ejemplo 3

    El siguiente archivo BAT nos lista todos los archivos ejecutables (.exe, .com, .bat) del directorio pasado desde lnea de comandos. (Si no pasamos argumento, muestra los del raz)

    @echo off FOR %%X IN (%1\*.exe %1\*.com %1\*.bat) DO echo %%X

    MEJORAS en el FOR

    Cuando las extensiones de comandos estn habilitadas (por defecto lo estn, ms informacin: CMD /? ), el comando FOR admite una serie de parmetros que amplan su funcionalidad:

    FOR /R [ruta] %V IN (lista) DO comando

  • C:\bat2exe.com C:\editpad.zip C:\LANGUAGE.txt ... C:\WINNT\discover.exe C:\WINNT\explorer.scf C:\WINNT\winhlp32.exe ... C:\WINNT\system32\mscoree.dll C:\WINNT\system32\msorcl32.dll C:\WINNT\system32\aaaamon.dll ...

    Ejemplo 2: Visualizamos todas las dll y exe a partir de C:\WINNT:

    C:\>for /R C:\winnt %x in (*.dll *.exe) do @echo %x C:\winnt\twain.dll C:\winnt\twain_32.dll C:\winnt\vmmreg32.dll C:\winnt\system32\mscoree.dll C:\winnt\system32\msorcl32.dll C:\winnt\system32\mmc.exe C:\winnt\system32\wscript.exe C:\winnt\system32\javaws.exe ...

    2 - Con el parmetro /D recorre los directorios, en lugar de los ficheros:

    C:\>for /D %x in (*) do @echo %x WINNT Documents and Settings Archivos de programa prog ...

    3 - Con el parmetro /L podemos crear el tpico bucle por contador:

    FOR /L %NombreVariable IN (inicio salto final) DO comando

    podemos separar "inicio", "salto" y "final" por comas ( , ) o punto y coma ( ; ).

    Con el siguiente archivo bat creamos archivos txt vacos, cuyo nombre y cantidad especificamos desde lnea de comandos:

    C:\pruebas>copy con crea.bat @ECHO OFF FOR /L %%A IN (1 1 %1) DO ECHO 2> %2%%A.txt >NUL ^Z 1 archivos copiados. C:\pruebas>crea 5 churro

  • C:\pruebas>DIR CH* /B churro1.txt churro2.txt churro3.txt churro4.txt churro5.txt

    El siguiente archivo BAT, hace un ping a broadcast, mostrando slo la direcciones de aquellos que contestan:

    C:\pruebas>more > pingred.bat @ECHO OFF SET RED=192.168.1. FOR /L %%H IN (1, 1, 255) DO ping -n 1 %RED%%%H | FIND "TTL=" ^Z C:\pruebas>pingred Respuesta desde 192.168.1.1: bytes=32 tiempo=1ms TTL=128 Respuesta desde 192.168.1.13: bytes=32 tiempo

  • X:\>for /F "tokens=1,3,5" %i in (fich.txt) do @echo %i - %j - %k El - y - cerebro, que - llevan - primaca la - son - que coplas - Jorge - a

    Podemos escoger rangos, en el siguiente ejemplo nos quedamos con las 3 primeras palabras y la 5:

    X:\>for /F "tokens=1-3,5" %a in (fich.txt) do @echo %a %b %c - %d El corazn y - cerebro, que se llevan - primaca la razn, son - que coplas de Jorge - a

    Y si deseamos la lnea completa a partir de la 7 palabra:

    X:\>for /F "tokens=7*" %A in (fich.txt) do @echo %A %B dos grandes vsceras los sentimientos y de el arranque de las muerte de su padre.

    Y si queremos toda la lnea, seleccionaremos todos los tokens de cada lnea:

    X:\>for /F "tokens=*" %m in (fich.txt) do @echo [ %m ] [ El corazn y el cerebro, las dos grandes vsceras ] [ que se llevan la primaca de los sentimientos y de ] [ la razn, son las que presiden el arranque de las ] [ coplas de Jorge Manrique a la muerte de su padre. ]

    delimitadores

    En los ejemplos anteriores los "tokens" coincidan con las palabras, pues para separarlos se han utilizado el espacio en blanco y la tabulacin. Podemos modificar los delimitadores con la clusula delims=

    En el siguiente ejemplo anulamos los delimitadores y obtenemos lo mismo de antes:

    X:\>for /F "delims=" %K in (fich.txt) do @echo [ %K ] [ El corazn y el cerebro, las dos grandes vsceras ] [ que se llevan la primaca de los sentimientos y de ] [ la razn, son las que presiden el arranque de las ] [ coplas de Jorge Manrique a la muerte de su padre. ]

    Utilizamos como delimitadores los signos de puntuacin (punto, coma, punto y coma, y dos puntos) - no debe haber espacios entre ellos- y nos quedamos con el primer token:

    X:\>for /F "delims=.,;:" %m in (fich.txt) do @echo %m El corazn y el cerebro que se llevan la primaca de los sentimientos y de la razn

  • coplas de Jorge Manrique a la muerte de su padre

    Podemos combinar delimitadores y tokens:

    for /F "tokens=1,2,3 delims=.,;:" %M in (fich.txt) do @echo %M %N %O

    Y utilizar otras clusulas, como skip=n, que se saltara las n primeras lneas del archivo, empezando a procesar en la n+1, o eol=carcter, que interpreta las lneas que comienzan por ese carcter como lneas de comentario y no sern procesadas, o useback que cambia la semntica de la lista: (`comando`) , ('cadena') , (archivo) ("archivo1 archivo2 archivo3")

    B) COMANDO

    El funcionamiento es similar al de los ficheros, nicamente que tendremos que encerrar el comando con comillas simples:

    X:\>for /F "tokens=15 delims=: " %x in ('ipconfig ^| find "IP"') do set myIP=%x x:\>set myIP myIP=192.168.1.33

    Observar el carcter de escape ^ necesario para que el pipe lo interprete dentro del comando en lugar de ser interpretado para el FOR.

    C) CADENA

    Con el siguiente comando aadimos la fecha a un nombre de archivo:

    X:\>type rdate.bat for /f "tokens=2-4 delims=/ " %%W in ("%date%") do ren %1 %%Y%%X%%W-%1 X:\>rdate backup.bat Ejecuta: ren backup.bat 20060219-backup.bat

    FORMATOS DE SALIDA

    Podemos especificar un formato para la variable del for. Por ejemplo:

    C:\Documents and Settings\sirio>for %x in (*) do @echo %~fsx C:\DOCUME~1\sirio\mueve.bat C:\DOCUME~1\sirio\TEMPFI~1.DIF f: ruta completa s: short name C:\DOCUME~1\sirio\EXCURS~1.TXT C:\DOCUME~1\sirio\EXCURS~2.TXT C:\DOCUME~1\sirio\EXCURS~3.TXT C:\DOCUME~1\sirio\ABC~1.TXT C:\DOCUME~1\sirio\DIAD~1.TXT C:\DOCUME~1\sirio\HID~1 C:\DOCUME~1\sirio\FONTS~1.CAC C:\Documents and Settings\sirio>for %x in (*) do @echo %x mueve.bat tempfile.diff

  • Excursiones.txt Excursiones del ao 2004.txt Excursiones del ao 2005.txt A B C.txt dia D.txt .hid .fonts.cache-1

    O simplemente %~X, que elimina las comillas (si las tuviera) como vimos arriba.

    Podemos consultarlos todos ejecutando for /?

    Acortar direcciones:

    Cuando usamos un for para recorrer los archivos nos devuelve la direccin entera del archivo. Esto es molesto, cuando lo que queremos es solo su nombre, o saber su ubicacin. Ahora les voy a ensear una tcnica para acortar esas direcciones. En el caso por ejemplo de que la variable X tenga la direccin de un archivo y solo quisiramos saber su extensin, usaramos: %~Xx y si quisiramos saber en que unidad se encuentra: %~dX

    Para entender un poco mejor esto, miremos esto como una sintaxis. Siempre se usara %~ seguido de una letra que representa lo que queremos obtener (el nombre, la extensin, etc) y por ultimo el nombre de la variable. Las letras que podemos usar son:

    f Ruta y Nombre d Nombre Unidad donde se encuentra p Solo ruta n Solo nombre x Extensin s Ruta abreviada a Atributos t Fecha y hora de creacin z Tamao del archivo

    Por ejemplo, este programa nos mostrara algunos datos de los archivos que existan en la misma carpeta y directorios superiores.

    @echo off FOR /R %%X in (*) DO ( echo Nombre: %%~nX echo Extension: %%~xX echo Tamao: %%~zX echo. )

  • Expansin de variables retardada

    Cuando aparecen variables de entorno en las estructuras IF y FOR, su valor es calculado al inicio de stos, y ya no se modifica hasta que finaliza el bucle for o la agrupacin de sentencias.

    El siguiente programa debera contar el nmero de veces que aparece la palabra %2 en el fichero %1:

    @echo off set cont=0 for /f "tokens=*" %%L in (%1) do ( for %%P in (%%L) do ( if /I "%%P"=="%2" set /A cont=%cont%+1 ) ) echo En %1 aparece %cont% veces la palabra %2

    Pero la ejecucin siempre nos da el mismo resultado:

    Z:\pruebas>cuenta Quijote.txt sancho En Quijote.txt aparece 0 veces la palabra sancho

    Pues la variable cont se sustituye por su valor (0) al entrar en el bucle y siempre estoy ejecutando la instruccin:

    if /I "%%P"=="%2" set /A cont=0+1

    Por lo que el resultado final del programa ser 0 1 (depende de si el ltimo IF de todos es cierto o no)

    La solucin es utilizar una shell con "sustitucin de variables retardada", donde las variables que deseemos que se sustituyan en el mismo instante de su utilizacin las encerraremos con admiraciones.

    Deberemos cambiar la lnea anterior por:

    if /I "%%P"=="%2" set /A cont=!cont!+1

    Y ejecutar el programa en una shell con susitucin retardada:

    cmd /v:on

    Aunque si deseamos que el programa bat se ejecute por defecto, con sustitucin de variables retardada, podemos aadir como primera lnea:

    SETLOCAL ENABLEDELAYEDEXPANSION

    Subrutinas: Llamar a un fichero BAT desde otro fichero BAT

    Desde un fichero BAT podemos invocar la ejecucin de otro fichero BAT (subrutina) de varias formas:

  • 1: Llamada sin retorno: Escribiendo el nombre de otro archivo bat En este caso el control se transfiere de un programa bat a otro, por finalizada la ejecucin del programa bat que realiz la llamada (es como un GOTO sin retorno).

    Por ejemplo, con los siguientes archivos bat:

    --- principal.bat --- rutina.bat

    @echo off echo INICIO PRINCIPAL set x=PRINCIPAL rutina echo VARIABLE X: %x% echo FIN PRINCIPAL

    @echo off echo ejecutando el subprograma ... echo variable x: %x% set x=SUBPROGRAMA echo variable x: %x% echo finalizando el subprograma

    El resultado de la ejecucin sera:

    Z:\pruebas>principal INICIO PRINCIPAL ejecutando el subprograma ... variable x: PRINCIPAL variable x: SUBPROGRAMA finalizando el subprograma Z:\pruebas>set x x=SUBPROGRAMA ( se han ejecutado en la misma shell )

    2: Ejecucin en subshell: se abre una subshell donde se ejecutar el subprograma: cmd /c progbat2

    Al abrirse una nueva subshell, todas las variables de entorno que defina en la subrutina se pierden al volver a la shell principal. Cuando finaliza la subrutina, se contina con la ejecucin del programa principal.

    En el programa "principal.bat", cambiamos la lnea de llamada por: cmd /c rutina

    El resultado de la ejecucin es:

    Z:\pruebas>principal INICIO PRINCIPAL ejecutando el subprograma ... variable x: PRINCIPAL

  • Ejecuta la subrutina y el programa principal en la misma shell, por tanto las modificaciones hechas en el entorno desde el subprograma, afectan al programa principal. cuando finaliza la subrutina, contina la ejecucin en el progama principal.

    Si en el programa principal anterior sustituimos la llamada por CALL rutina obtenemos:

    Z:\pruebas>principal INICIO PRINCIPAL ejecutando el subprograma ... variable x: PRINCIPAL variable x: SUBPROGRAMA finalizando el subprograma VARIABLE X: SUBPROGRAMA

  • siendo la etiqueta :FIN la ltima lnea del programa. O incluso EXIT /B n , si necesitamos

    devolver un cdigo de retorno (errorlevel).

    En la subrutina slo ser necesaria si hubiera cdigo debajo de sta.

    El siguiente ejemplo es una demostracin de cmo podra convertirse a maysculas :

    Z:\pruebas>type mayuscular.bat @echo off set /P x="Dime algo: " call :toUpperCase %x% echo [ %x% ] exit /b :toUpperCase set x=%* set x=%x:a=A%

  • 2.Variables

    Para ver todas las variables usamos el comando set. Si escribimos set y luego enter veremos todas las variables. Estas son las variables mas usadas: Citar

    %ALLUSERSPROFILE% C:\Documents and Settings\All Users (Ruta de la carpeta con la configuracin para todos los usuarios)

    %APPDATA% C:\Documents and Settings\{usuario}\Datos de Programa (Ruta de la carpeta con datos de programa)

    %COMPUTERNAME% Nombre del equipo (Nombre del equipo)

    %COMSPEC% C:\Windows\System32\cmd.exe ( Ruta al intrprete de comandos)

    %HOMEDRIVE% Unidad donde estan los datos del usuario (C:) (Unidad en la que se encuentra los datos de usuario)

    %HOMEPATH% \Documents and Settings\{usuario} (Ruta a la carpeta del usuario actual)

    %USERPROFILE% C:\Documents and Settings\{usuario} (incluye unidad)

    %PATH% C:\Windows\System32\;C:\Windows\ (Rutas en la que se buscan ejecutables)

    %PATHEXT% .COM; .EXE; .BAT; .CMD; .VBS; .VBE; .JS ; .WSF; .WSH. (Extensiones de archivo ejecutables)

    %PROGRAMFILES% C:\Archivos de programa (Ruta de la carpeta archivos de programa)

    %PROMPT% $P$G (Formato del intrprete de comandos)

    %SYSTEMDRIVE% C: (Unidad en la que se ha instalado Windows)

    %SYSTEMROOT% y %WINDIR% C:\Windows (Contiene la carpeta de Windows)

    %TEMP% y %TMP% C:\DOCUME~1\{usuario}\LOCALS~1\Temp (Ruta de la carpeta Temp)

    %USERNAME% Ej.:Computer (Nombre de usuario actual)

    %DATE% 31/12/2009 (Fecha actual)

    %TIME% 00:00:00,00 (Hora actual)

    %CD% C:\ (Carpeta actual con su ruta completa)

    %ERRORLEVEL% 0 o 1 (Cdigo de salida del comando anterior)

    %RANDOM% 32767 (Nmero aleatorio de 0 a 32767)

  • Las variables nos sirven para indicar un valor que puede ser un numero una ruta o lo que queramos, en donde escribimos la variable estamos escribiendo en realidad el valor de la variable. A las variable se las seala con %% ejemplo para indicar la variable homepath escribiremos %homepath%.

    Por ejemplo podemos listar el contenido del escritorio sin estar en el, usando:

    dir /a "%homedrive%%homepath%\Escritorio", por las dudas siempre que nos referimos a una ruta usaremos comillas dobles "".

    Para establecer una variable hacemos Set variable=valor

    En variable el nombre de nuestra variable y en valor lo que queremos que valga la variable

    En el bat para que la variable la defina el usuario hacemos. Citar

    Set /p variable=

    No hay valor porque el valor lo define el usuario, el que abra el .bat

    Para definir variables como el resultado de sumas restas multiplicaciones divisiones. Citar

    Set /a variable=numero+numero Set /a variable=numero-numero

    Tambien si una variable es un valor numero podemos operar con ella por ejemplo Cdigo: DOS

    Set /a variable=%random%*%random%

    En este lenguaje Batch no tenemos soporte para comas, asi que si hacemos 3/2 no nos dara 1.5 sino 1 (redondea hacia abajo) Para mas informacin sobre variables set/?

    2.1.Recortar una variable

    Podemos tomar un trozo de una variable por ejemplo: Hay una variante llamada original y su valor es abcdefghijk

    Si queremos solo tener las letras fghi, tenemos que ver cuantas letras hay detras de la f en este caso serian 5 (abcde) y cuantos caracteres ocupa lo que queremos ver en este caso serian 4 (fghi). Citar

    %nombrevariante:~numerosdecaracteresanteriores,numerosdecaracteresqueabarca%

    En el ejemplo anterior seria (nos mostraria solo fghi) %original=~5,4%

    Ahora queremos mostrar a partir de la c incluida %original:~2%

    Ahora queremos mostrar los ultimos 3 caracteres %original:~-3%

    Ahora queremos mostrar todo menos los ultimos tres caracteres %original:~0,-3%

  • Para hacer el signo ~ lo hacemos con alt+126

    @ echo . @ echo Este archivo BAT sobreescribe los apk originales dentro de esta carpeta. @ echo . @ echo Haz copia de los mismos antes de ejecutarlo. @ echo . @ echo Copia los apk deoxdexados en este directorio antes de empezar. @ echo. @ echo Si deseas historial redirecciona la salida a un archivo @ echo . @ echo pulsa "ctrl+c" si deseas terminar la ejecucion @ echo . @ pause rem eliminamos forzando borrado del 1firmado*.* /F /Q del 0alineado*.* /F /Q rem Ahora firmamos con signapk FOR %%f IN (*.apk) DO java -jar signapk.jar testkey.x509.pem testkey.pk8 %%f 1firmado_%%f rem Ahora alineamos con zipaling FOR %%h IN (1firmado*.apk) DO zipalign -v 4 %%h 0alineado_%%h rem paso parametros a la etiqueta label @ FOR /R %%X in (0alineado*.apk) DO call:label %%~nX rem fin de bucle FOR goto:fin :label set uno=%1 set dos=%uno% rem renombro con copy forzando sobreescribir. Elimino la premisa (0alineado_1firmado_) copy %uno%.apk %dos:~19%.apk /Y rem informo fin de etiqueta para retorno a comando FOR goto:eof :fin del 1firmado*.* del 0alineado*.* echo programa terminado rem Ejemplo de recortar cadenas de caracteres en variables. @ set mia=1234567890 rem @ echo El numero central es %mia:~4,-5% rem @ echo Los cuatro ultimos numeros son %mia:~6% rem @ echo Los tres primeros numeros son %mia:~,-7%

  • pause ------------------------------------------------------------------------------- for /F %%M in ('dir *.apk /B /S') DO call:label %%M %%~dM %%~pM %%~nM %%~xM rem fin de bucle FOR goto:fin :label set uno=%1 set unidad=%2 set ruta=%3 set nombre=%4 set nombre_recortado=%nombre:~4% set extension=%5 rem copio archivo modificado el nombre copy %uno% %unidad%%ruta%%nombre_recortado%%extension% /Y rem borro archivo original del %uno% /F /Q rem informo fin de etiqueta para retorno a comando FOR goto:eof :fin @ echo FIN DEL PROGRAMA --------------------------------------------------------------------------------- :: CarlitoS.dll :: Bat que borra 4 ultimos caracteres de los nombres de varios archivos aceptando archivos que incluyan nombres con espacios. :: Ubicar este bat en la misma carpeta de los archivos a renombrar. @echo off set ext=xls rem ext es la extension de los archivos sin anteponer punto. set sacar=4 rem sacar es la cantidad de letras al final del nombre que quieres sacar. for /f "tokens=*" %%f in ('dir /b /a *.%ext%') do call :lab %%f exit :lab set original= set original=%* set newname= call set newname=%%original:.%ext%=%% call set newname=%%newname:~0,-%sacar%%%.%ext% if "%newname%"==".%ext%" (goto :eof) ren "%original%" "%newname%" goto :eof

    Hoy les traigo un tutorial sobre el comando set con algunos descubrimientos. Luego publicar algunas cosillas ms. Espero que les guste!

  • Autor: Tempestinfinit Fecha: 13/10/2009 Tema: Comando Set Separador de expresiones mediante el comando set (set /a): Se puede utilizar el separador de expresiones o la (,) como se encuentra explicado en la ayuda del comando Set, para declarar varias variables (siempre que sean numricas), utilizando el comando set y el modificador /a (set /a) una sola vez y en una sola lnea. () - agrupar ! ~ - - operadores unarios * / % - operadores aritmticos + - - operadores aritmticos > - desplazamiento lgico & - bit a bit y ^ - bit a bit exclusivo o | - bit a bit = *= /= %= += -= - asignacin &= ^= |= = , - separador de expresiones Cualquier cadena de la expresin que no sea numrica, se tratar como variable de entorno cuyo valor se convertir a tipo numrico antes de usarse. Si se especifica una variable que no est definida en el entorno actual, se usar el valor cero. Ejemplos: 1) Declarar a=1, b=1, c=1, d=1 a) set /a a=1,b=1,c=1,d=1 (esto generalmente se usa cuando tenemos varios valores, pero tambin sirve) b) set /a a=b=c=d=1 c) set/aa=b=c=d=1 (tambin funciona de esta manera para los que quieran ahorrarse 2 bytes) 2) Declarar a=1, b=2, c=3, d=4 a) set /a a=1,b=2,c=3,d=4 3) Tambin podemos incluir variables no declaradas anteriormente (siempre y cuando las variables sean declaradas mientras se realiza la operacin con ellas sino se tomarn como 0). a) set /a a=1,b=a+1,c=b+1,d=c+1 4) Declarar a=(b=2 y c=4) y luego a=(b+c). Nota: a, b y c no fueron declaradas antes. a) set /a a=(b=2)+(c=4) 5) Declarar b=2*a , c=2*b , d=2*c (No conocemos a pero suponemos que est declarada, adems queremos que b sea 2 veces a y as. Esto generalmente lo vamos a usar en un fichero BAT).

  • a) set /a b=2*a,c=2*b,d=2*c 6) Podemos utilizar variables declaradas anteriormente para asignarlas a otras variables. Declaramos a=1, b=2 y c=3. a) set /a abc=(%a%%b%%c%) ,(recuerden que a, b y c tienen que estar declaradas). 7) Declaramos a=1, b=2, c=3 y asignamos a, b y c a abc. Esto es puramente matemtico y no hay otra manera al menos de declarar 3 variables y luego asignar a una cuarta (al menos no en una lnea). Esto conlleva a la complicacin de que, si no sabemos cuantas cifras tiene el nmero en la variable que queremos asignar, no se puede hacer (al menos no sin obtener un error). a) set /a abc=(a=1,b=2,c=3,a*100+b*10+c) b) set /a a=1,b=2,c=3,abc=a*100+b*10+c Subcadenas: Declaramos ABC=abcdefghijklmnopqrstuvwxyz %ABC:~desplazamiento,longitud% %ABC:~6,5% (desplaza 6 caracteres y muestra 5 a partir del 6to) ghijk %ABC:~10% (desplaza 10 y sino se especifica la longitud utiliza el resto de la cadena como longitud) klmnopqrstuvwxyz Si algn nmero (desplazamiento o longitud) es negativo, entonces el nmero usado es la longitud del valor de la variable de entorno agregado al desplazamiento o longitud especificados. %ABC:~-10% (extrae los 10 ltimos) qrstuvwxyz %ABC:~0,-10% (extrae los 10 primeros, o sea, se ubica al principio de la cadena y muestra 10) abcdefghij %ABC:~0,-2% (muestra todos menos los ltimos 2) abcdefghijklmnopqrstuvwx %ABC:~-2% (desplaza 0 muestra los ltimos 2) yz Anteriormente si queramos obtener la fecha o la hora en 3 variables utilizando una sola lnea debamos hacer esto: set dia=%date:~0,2% & set mes=%date:~3,-5% & set ao=%date:~-4% Ahora: 8 ) Obtener la fecha en 3 variables utilizando un solo set /a. a) set /a dia=%date:~0,2%,mes=%date:~3,-5%,ao=%date:~-4% 9) Obtener la hora en 3 variables utilizando un solo set /a (se complica un poco ms).

  • a) set /a hora=%time:~0,2%,min=%time:~3,-6%,a=%time:~6%,b=%time:~-2%,seg=a*100+b 10) Incluso si queremos combinar la 8 y la 9 para ahorrarnos un set /a podemos. a) set /a dia=%date:~0,2%,mes=%date:~3,-5%,ao=%date:~-4%, hora=%time:~0,2%,min=%time:~3,-6%,a=%time:~6%,b=%time:~-2%,seg=a*100+b

    Sustitucin de variables: Con el comando set y el modificador /a (set /a) podemos realizar sustituciones simples y compuestas(con algunas excepciones) de subcadenas y recuerden que siempre con el modificador /a hablamos de nmeros. Algunos ejemplos: a) Declaramos a=123456789 set /a a=%a:123=999% (Sustitumos la subcadena numrica 123 por 999) 999456789 b) set /a a=(%a:123=456%),(%a:456=789%),(%a:789=8910%) (Sustitumos 123 por 456, 456 por 789 y 789 por 8910) 4564568910 Sumando variables con espacios o guiones: Si queremos sumar variables con espacios o con guiones no se podra. Ejemplo: set /a trata de aprender+=1 (esto da error) set /a trata-de-aprender+=1 (esto da error) Entonces se me ocurri utilizar los caracteres (representa al guin) y ( representa al espacio en blanco) para sustituirlas por el espacio en blanco tradicional y el guin, de manera de poder sumar una variable que contengan espacios en blanco y guiones. Ejemplos: Declarando variables... 1) set "tempest=" 2) set "varnula=^" Resultado: 1) a a (se encuentra en medio de las dos a) 2) aa (variable nula, no existe? :XD se supone que esta en el medio de las dos a) Ahora viene lo interesante! Declaramos las siguientes variables: 1) set /a "+=1" 2) set /a "+=1" 3) set /a "HolaatodossoyTempestBP+=1" Resultado: 1) 1

  • 2) 1 3) 1 Conclusin: Obviamente el espacio en blanco no existe, ya que no tiene sentido pensar en nada, en fin, los dos caracteres que utilic al mostrarse con el comando echo representan el espacio y el guin, de manera que pueden utilizarse para trabajar en memoria. Sin embargo al redireccionarlos a un archivo de texto, los muestra como y , realmente como lo que son. Incluyendo comandos entre las sustituciones.... Ejemplos: Declaramos a=123456789 a) set /a a=(%a:123=456%)&echo 1-OK,(%a:456=789%)2-OK,(%a:789=7890%)3-OK 1-OK,(123789789)2-OK,(123456789)3-ok b) set /a a=(%a:123=456%)&pause,(%a:456=789%)&pause,(%a:789=7890%)&pause (Incluimos una pausa entre cada sustitucin) c)set /a a=(%a:123=456%)&set b=,(%a:456=789%),(%a:789=7890%) (Tambin podemos incluir el comando set)

    Llamadas a etiquetas: Esta tcnica nos permite hacer una llamada a una etiqueta y luego al finalizar continuar declarando el resto de las variables. Ejemplo: @echo off set a=123456789 set /a a=(%a:123=456%)&call:C1,(%a:456=789%)&call:C2,(%a:789=0%)&call:C3 :C1 echo Trata de goto :eof :C2 echo aprender todo goto :eof :C3 echo lo que puedas Trata de aprender todo lo que puedas Errores: Se produce un error con algunos nmeros que creo empiezan con 0, la ayuda del DOS nos dice: Los valores numricos son nmeros decimales, a no ser que lleven el prefijo 0x delante para los nmeros hexadecimales, y 0 para los nmeros octales. De esta manera 0x12 es lo mismo que 18, y lo mismo que 022.

  • Nota: la notacin octal puede ser confusa: 08 y 09 no son nmeros vlidos porque 8 y 9 no son dgitos octales vlidos.

    Sustituir dentro de una cadena, un literal por otro: %var:str1=str2% Este comando buscar todas las ocurrencias de la subcadena str1 dentro de var cambindolas por str2. Por ejemplo: set var=hola cmo ests Ejecutad para verlo: echo %var:cmo=que tal% Igualmente podramos asignrselo de nuevo a var o bien a otra nueva variable de entorno. Por ejemplo: set var=%var:cmo=que tal% con lo cual el contenido habra quedado modificado. NOTA1: puede omitirse str2. En ese caso la cadena str1 dentro de la variable var quedar eliminado. Por ejemplo: set var=12345xx6 set var=%var:xx=% echo %var% NOTA2: se cambiarn todas las ocurrencias de str1. Si str1 figura varias veces se cambiar todas las veces en la cadena de caracteres.

    LENGUAJE DE COMANDOS SCRIPTS .CMD .BAT Qu es un script en lenguaje de comandos? No es nada ms que un fichero de texto, que puede generarse con el simple cuaderno de notas, y cuya extensin es .bat o .cmd. Su contenido son los comandos que ejecutaramos en una consola de comandos (cmd) y cuyo fin es evitar las tareas repetitivas que podramos realizar en una consola de comandos. Aunque esta es la definicin clsica, no debemos perder de vista que desde una consola de comandos podemos realizar, mediante comandos, prcticamente todo lo que la imaginacin nos permita. Todo lo que se configura, o las tareas de mantenimiento que realizamos en Windows se pueden hacer desde una consola de comandos. Igualmente existen muchos comandos que son slo de consola. Revisemos un poco la tipologa de los comandos: un comando es algo que o bien entiende directamente el shell (el intrprete de comandos, en este caso el cmd.exe) o bien es un programa con extensin .com o .exe -o incluso un visual basic- que no use la interfaz grfica y que por tanto est orientado a la consola. Un ejemplo clsico es el programa ipconfig. Este programa (de consola) nos da la configuracin TCP/IP de la mquina. O bien el programa ping. ENTORNO DE UN PROGRAMA Todos los sistemas operativos, y Windows no es una excepcin, tienen un rea de datos llamada entorno. No es nada ms que un rea donde se guardan ciertas variables con su contenido. Es importante entender que cada programa de Windows tiene su entorno (igual o diferente a otro programa). Los entornos se heredan. Cada programa (y el propio intrprete de comandos, cmd.exe, es un programa ms) cuando se lanza, hereda dicho entorno. Por heredar, no quiere decir que use el mismo que el programa padre, sino que al lanzarse, el loader -cargador- del sistema operativo realiza una copia del entorno padre en una nueva rea de datos y al lanzar el programa le da como

  • direccin del rea de entorno esa nueva copia del entorno del padre. En otras palabras, cualquier modificacin en las variables de entorno dentro de un programa no afecta al sistema ni al resto de programas, ya que lo que hara es modificar su propio entorno: la copia del entorno original del programa padre. El sistema operativo al cargarse predefine ya una serie de variables de entorno. Podemos verlas, bien con botn derecho en Mi PC / propiedades / pestaa de opciones avanzadas / botn de variables de entorno, o bien de una manera ms simple, lanzando el intrprete de comandos (cmd.exe) y tecleando el comando set (sin comillas). NOTA: Realmente, aunque lo veamos en conjunto, existen dos entornos: uno del sistema y uno de usuario, pero la visin de ambos es el conjunto de los dos. Acabamos de ver nuestro primer comando: set. Este comando nos permite no slo ver todas las variables, sino tambin definir, cambiar, borrar su contenido y algunas opciones ms. Si lo ejecutamos por consola, nos dar algo similar a: ALLUSERSPROFILE=C:\Documents and Settings\All Users APPDATA=C:\Documents and Settings\mi usuario\Datos de programa CommonProgramFiles=C:\Archivos de programa\Archivos comunes COMPUTERNAME=MIMQUINA ComSpec=C:\WINDOWS\system32\cmd.exe FP_NO_HOST_CHECK=NO HOMEDRIVE=C: HOMEPATH=\Documents and Settings\mi usuario NUMBER_OF_PROCESSORS=1 OS=Windows_NT Path=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;..etc PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH PROCESSOR_ARCHITECTURE=x86 PROCESSOR_IDENTIFIER=x86 Family 6 Model 7 Stepping 3, GenuineIntel PROCESSOR_LEVEL=6 PROCESSOR_REVISION=0703 ProgramFiles=C:\Archivos de programa etc Fijmonos que la estructura es: nombre de variable=contenido de la variable Las variables, dentro de una consola de comandos o bien dentro de un script se referencian para poder ver su contenido encerradas entre smbolos de %. Por ejemplo, en el caso anterior, para ver el contenido de la variable COMPUTERNAME, simplemente podemos ejecutar: echo %COMPUTERNAME% Esto nos dar como resultado: MIMQUINA Igualmente podramos cambiarlo con el comando set citado anteriormente: set COMPUTERNAME=nuevoNOMBRE Pero * Esto realmente tiene el efecto de cambiar el nombre del ordenador? por supuesto que no. Esto slo cambia el contenido de dicha variable. Dnde lo cambia? pues tal y como hemos comentado anteriormente, lo cambia en el entorno del programa, es decir, en la copia del entorno original heredado por el programa. En nuestro caso, al ejecutarlo desde un cmd.exe, implica que cambia el entorno del cmd.exe (y slo de l, es decir, si tuvisemos lanzadas dos consolas de comandos, cada

  • una de ellas con cmd.exe, slo se cambiara en el cmd.exe que hayamos ejecutado ese comando set). Y para que puede servir? simple, si recordamos que un programa hereda una copia del entorno del programa que lo lance, esto implicar que todo lo que lancemos desde esa consola de comandos, tendr el contenido de esa variable modificado. * Cmo podemos crear una nueva variable de entorno? tan simple como darle un nombre y asignarle su contenido. Por ejemplo: set nuevo=prueba Esto crear si no existe, o modificar el contenido si existiese, de una variable de entorno llamada nuevo, y le asignar el contenido de prueba. * Podemos asignar a una variable el contenido de otra?: s, por supuesto. Simplemente recordando que el contenido de una variable es precisamente el nombre de la variable encerrada entre smbolos %. set otra=%nuevo% Esto crear la variable otra con el contenido de la variable nuevo, el cual era el texto prueba. Si despus de ejecutar el comando anterior realizamos: echo %otra% su resultado ser: prueba * Cmo podemos borrar -eliminar- una variable? simplemente no asignando nada. set otra= En este caso borrar la variable. Si ahora damos el comando set que nos muestra todas las variables, la variable otra ya no aparecer. * Puedo concatenar textos con variables en una asignacin?: S, por supuesto. Por ejemplo: set otra_de_nuevo=Esto es una %nuevo% de concatenacin El resultado de lo anterior ser que la variable otra_de_nuevo contendr el valor Esto es una prueba de concatenacin. * Podemos tener contenidos numricos y no slo alfabticos, y por tanto realizar operaciones matemticas con el comando set? s, se puede. La manera es con el modificador /a. Pongamos un ejemplo: set n=234 (asignar 234 a la variable n) set /a i=%n%/4 Veremos que esto nos devuelve por pantalla el valor 58 (es decir la divisin de 234/4) y adems se lo asigna a la variable i. Es necesario el modificador /a, ya que si no lo hubisemos puesto, la expresin: set i=%n%/4 no hubiese realizado la operacin matemtica y se hubiese quedado con el contenido (como literal) de: 234/4 es decir, una cadena de caracteres con ese contenido y no con el resultado matemtico de la divisin. Fijmonos, por curiosidad en este ltimo caso y se puede ir realizando una prueba en una consola de comandos. Realicemos: set n=234

  • set i=%n%/4 echo %i% veremos entonces: 234/4 Si ahora realizamos: set /a j=%i% Que contendr? Contendr el literal de texto 234/4? O slo 234 ya que el carcter / no es numrico? O contendr 58? Realizadlo como prueba La asignacin a una variable numrica, puede ser decimal, hexadecimal u octal. Podemos hacer: set /a i=14 set /a i=0x0E en ambos casos contendr el decimal 14 (recordemos que el hexadecimal 0E equivale al decimal 14). O bien, si queremos introducir un numero en octal, simplemente lo empezamos por cero. set /a i=021 hay que tener cuidado con esto, ya que el octal 021 es el decimal 17. Podis comprobarlo en pantalla simplemente tecleando la lnea anterior y viendo el resultado. Siempre los resultados nos los expresar en decimal. Esto puede ser til para convertir directamente de hexadecimal o bien de octal a decimal de una manera rpida. * Ya que hemos empezado con el comando set vamos a finalizar todo lo que dicho comando puede hacer. Adems de lo anterior: set p nos mostrar en pantalla todas las variables de entorno que empiecen por p. Y para finalizar el modificador /p. Es decir, una sintaxis del estilo: set /p variable=[literal] lo que hace es muestra el literal en pantalla y el cursor se queda a continuacin esperando que metamos un dato. Cuando lo metemos y tecleamos intro, lo que hayamos tecleado se asignar a la variable de entorno definida en el set. Por ejemplo: set /p dato=Introduce datos: Nos mostrar por pantalla: Introduce datos:_ y cuando introduzcamos los datos los asignar a la variable dato. Esto es vlido realizarlo en un script. En ese momento se detendr la ejecucin del script y nos pedir datos por pantalla. Al pulsar la tecla intro, se los asignar a dicha variable y continuar la ejecucin del script. CARACTERES ESPECIALES Hay ciertos caracteres especiales que hay que usar con extremada precaucin: por ejemplo, evitar usar, a no ser que lo necesitemos explcitamente, caracteres reservados como &, >,
  • nos dar un error que veremos por pantalla: a no se reconoce como un comando interno o externo, programa o archivo por lotes ejecutable * Qu ha hecho el sistema? Ha ejecutado el comando que hay antes del &, es decir: set var=a Por tanto le ha asignado a la variable de entorno var el contenido a. A continuacin, el intrprete de comandos intenta ejecutar lo que hay despus del &, es decir intenta interpretar el comando a. Como a no es un comando reconocido, ni un .exe, ni un .com, ni el nombre de otro script nos dar el error mostrado anteriormente. Curiosamente: set var=a&cmd qu hace? Ejecutadlo y ved el resultado. Pero y si realmente queremos asignar el contenido del literal a&a a la variable var, cmo lo hacemos? Simplemente anteponiendo el carcter ^ a cualquiera de los caracteres especiales. En nuestro caso deberamos haber hecho: set var=a^&a Si posteriormente ejecutamos un: echo %var% nos seguir mostrando un error, ya que aunque realmente tiene el contenido a&a, nos mostrar a e intentar ejecutar lo que va a continuacin: intentar la ejecucin de un comando llamado a. Para ver que realmente tiene el contenido solicitado, podemos hacer dos cosas: set v el nos mostrar el contenido de todas las variables que empiezan por v y podremos comprobar que la variable var contiene lo que realmente desebamos. O bien, redirigir la salida a un archivo (los smbolos de redireccin y su significado los veremos ms adelante). NOTA: Un error bastante corriente cuando se usan caracteres de asignacin y concatenacin (&) en la misma lnea puede ser: set var=prueba & set var1=otra_prueba Cul es, o puede ser, el error cometido? puesrecordemos que todo lo anterior al & se ejecuta como un comando. Es decir: qu hemos asignado a la variable var? podemos suponer que prueba. Pero no es as, hemos asignado todo lo anterior al &, es decir prueba , con un espacio en blanco al final. Esto nos puede causar problemas posteriores si lo que queramos hacer era asignar slo prueba. Podemos verificarlo tecleando entre algn delimitador, por ejemplo un *: echo *%var%* Lo cual nos mostrar un *, el contenido de var y otro *. Obtendramos: *prueba * con el fatdico (en este caso) carcter en blanco al final. OPERACIONES CON VARIABLES DE ENTORNO Hemos visto hasta el momento que las variables de entorno no son nada ms que cadenas de caracteres, las cuales mediante algn modificador especial en el comando set (/a) pueden tratarse como numricas para realizar algunas pequeas operaciones matemticas. Vamos a ver primero las funciones que podemos aplicar a las variables de caracteres y en segundo lugar las operaciones matemticas que podemos hacer as como su precisin cuando el contenido es numrico. Igualmente veremos las llamadas variables dinmicas de entorno: variables que aunque no veamos mediante el comando set pueden usarse en instrucciones de comandos. Tengamos siempre presente que los caracteres especiales deben llevar el smbolo ^ precedindolos. Por ejemplo, un error que viene en la propia ayuda de Windows del comando set, es que la propia ayuda nos dice: El comando SET no permitir que un signo de igual sea parte de una variable. Esto no es del todo verdad. Si hacemos: set var=a^=b la variable var quedar con el contenido a=b. Se puede comprobar si a continuacin de lo anterior ejecutamos: set v 1) FUNCIONES SOBRE VARIABLES DE CARACTERES * Extraer una subcadena: %var:~n,m% Esto nos extrae de la variable var, la subcadena desde la posicin n con longitud m. n es el desplazamiento empezando a contar desde 0, por tanto, la primera posicin es la 0, la segunda

  • la 1, etc. Pongamos un ejemplo: set var=123456789 echo %var:~1,4% nos mostrar la subcadena de var que va desde la posicin 2 (recordemos: con desplazamiento +1 ya que empieza por 0) y con longitud 4. Es decir, veremos: 2345. Tanto n como m, son opcionales. Es decir, por ejemplo: %var:~1% nos mostrar desde la posicin 2 (offset de 1), hasta el *final* de la variable (ya que no se ha especificado longitud). Por tanto, mostrar en el ejemplo anterior: 23456789. Igualmente: %var:~,5% al no especificarse posicin se asume desde el principio de la cadena y por tanto nos mostrar 5 caracteres iniciales. En nuestro caso 12345. NOTA: si n es un nmero negativo, se refiere a la longitud de toda la cadena menos ese nmero. Por ejemplo: set var=123456789 echo %var:~-2% nos mostrar los dos ltimos caracteres de la cadena, es decir 89. Igualmente, si m es negativo, se refiere a *toda* la cadena menos m caracteres. set var=123456789 echo %var:~,-2% nos mostrar todo menos los dos ltimos caracteres de la cadena, es decir 1234567. * Sustituir dentro de una cadena, un literal por otro: %var:str1=str2% Este comando buscar todas las ocurrencias de la subcadena str1 dentro de var cambindolas por str2. Por ejemplo: set var=hola cmo ests Ejecutad para verlo: echo %var:cmo=que tal% Igualmente podramos asignrselo de nuevo a var o bien a otra nueva variable de entorno. Por ejemplo: set var=%var:cmo=que tal% con lo cual el contenido habra quedado modificado. NOTA1: puede omitirse str2. En ese caso la cadena str1 dentro de la variable var quedar eliminado. Por ejemplo: set var=12345xx6 set var=%var:xx=% echo %var% NOTA2: se cambiarn todas las ocurrencias de str1. Si str1 figura varias veces se cambiar todas las veces en la cadena de caracteres. 2) FUNCIONES MATEMTICAS SOBRE VARIABLES DE ENTORNO Con el modificador /a en el comando set podemos realizar operaciones matemticas *simples* sobre variables. Debemos primero hablar de la precisin: slo se opera con nmeros enteros. Por tanto la divisin de 5/2 nos dar como contenido un 2. Igualmente la mxima precisin es 2^32. En general la sintaxis es: set /a var=expresin matemtica. Por expresin matemtica puede entenderse cualquiera de las siguientes y en orden de precedencia de mayor a menor (extrado de la propia ayuda del comando set): () agrupar ! ~ - operadores unarios * / % operadores aritmticos

  • + - operadores aritmticos > desplazamiento lgico (bit a bit) & bit a bit y ^ bit a bit exclusivo o | bit a bit = *= /= %= += -= asignacin &= ^= |= = , separador de expresin Si usamos una variable de entorno dentro de una expresin matemtica y dicha variable no existe, ser asumido que contiene un cero. Veamos los matices de lo anterior, ya que si no tenemos en cuenta algunas matizaciones ya comentadas en este documento habr expresiones que nos darn error. IMPORTANTE: Volvamos a recordar que hay smbolos especiales que no pueden escribirse directamente, por ejemplo: &, , |, o incluso ^. Cada uno de ellos debe ir precedido por un ^. Es decir, el bit a bit exclusivo ^, debe escribirse como ^^ ya que si no el intrprete de comandos lo interpretar errneamente. Veamos ejemplos de asignaciones. set /a x=x+1 podemos sustituirlo (abreviarlo) por una notacin similar al C o C++, es decir: set /a x+=1 (a la variable x sumarle 1 y asignrselo a x) Lo mismo: set /a x=x-1 es equivalente a: set /a x-=1 set /a x=x*23 es equivalente a: set /a x*=23 etc para el resto de operaciones matemticas de asignacin citadas anteriormente. Veamos el siguiente problema: qu solucin tiene? set /a x=8, y=2, z=16 set /a z-=(x-y)/2+5^
  • aparecen las variables de entorno en un script encerradas entre smbolos ! en vez de los clsicos % y cundo debemos usar el smbolo !. ATENCIN: El intrprete de comandos lee una lnea de ejecucin completa y lo primero que hace es sustituir las variables de entorno antes de procesarla. Esta mxima debemos tenerla presente siempre. Veamos un ejemplo que, aunque aparentemente est bien escrito, nos producir siempre resultados anmalos o no esperados: set var=antes if %var%==antes (set var=despues&if %var%==despues echo Cambiado a despues) Hemos introducido el comando if. Realmente un if no es nada ms que un si condicional en castellano. Es decir: si se cumple una expresin, entonces se ejecuta lo que va a continuacin. Si adems ponemos la palabra reservada else, esto se ejecutar en caso contrario. Recordemos igualmente que los parntesis tienen precedencia. Veamos entonces el conjunto de las instrucciones anteriores: asignamos antes a la variable var. En la segunda lnea preguntamos: Si la variable var contiene antes -que s que es verdad-, ejecutaremos: asignar a la variable var la palabra despues y adems a continuacin comprobar que si tiene el contenido de despues -lo cual parece que es evidente puesto que acabamos de hacerlo- sacaremos por pantalla el texto Cambiado a despues. Nos parece por tanto obvio que lo que vamos a ver despus de ejecutar los comandos anteriores es Cambiado a despues. Pues bien, si lo hacemossorprendentemente veremos que no sale nada. No lo cambia? Realmente lo cambia, porque si a continuacin de lo anterior ejecutamos: echo %var% veremos que contiene despues. Entonces por qu no ha ejecutado correctamente lo que tenemos despus del & en la lnea anterior? Volvamos a leer ahora despacio el prrafo que he comenzado anteriormente por ATENCIN. Repasemos lo que hace por defecto el intrprete de comandos: lee la lnea *entera* y en ese momento el contenido de las variables de entorno queda sustituido por el contenido real. A continuacin, ejecuta la lnea entera. Es decir lo primero que hace el intrprete de comandos es la expansin de la lnea, y por tanto, antes de ejecutarla, quedara: if antes==antes (set var=despues&if antes==despues echo Cambiado a despues) es evidenteque el segundo IF no lo ejecutar nunca. Este es el funcionamiento por defecto del intrprete de comandos. Si queremos que no funcione as, y que haga dinmicamente la expansin de las variables (y no antes de ejecutar la lnea de comando) hay que ejecutar dos cosas: 1) Arrancar el intrprete de comandos con el parmetro /V:ON para indicarle que debe expandir las variables. (Si estamos en un script, colocar como primera lnea del script: setlocal ENABLEDELAYEDEXPANSION. Lo veremos ms en detalle posteriormente) 2) Referenciar las variables que deben ser expandidas en ese momento, y no en el momento de leer la lnea por primera vez mediante los smbolos de ! en vez de %. En nuestro caso, y para verlo ms claro: 1) En inicio-ejecutar arrancamos el intrprete de comandos como: cmd /V:ON 2) Ejecutamos: set var=antes if %var%==antes (set var=despues&if !var!==despues echo Cambiado a despues) Ntese el cambio de % por ! en el segundo IF. En este caso podemos comprobar que la ejecucin es lo que desebamos. Volveremos con estos temas ms adelante. ENTENDIENDO LA ENTRADA/SALIDA BSICA DE COMANDOS Cuando ejecutamos un comando en una consola puede ser de dos tipos: o bien un comando

  • interno de la shell de comandos (cmd.exe) o bien un programa externo (.com, .exe, .bat, etc.). Lo primero que verifica el intrprete de comandos es si es un comando interno (por ejemplo copy). Si lo es, lo ejecuta directamente. Si no pertenece a su tabla interna de comandos, empieza su bsqueda: * Dnde y cmo lo busca? 1) Si se ha tecleado extensin del comando, por ejemplo: ping.exe se buscar slo con dicha extensin. Si no se ha tecleado extensin, es decir, simplemente es ping, lo primero que hace el sistema es localizar la variable de entorno %PATHEXT% para ver las posibles extensiones y su orden de bsqueda. En un entorno NT (y XP lo es), si ejecutamos: echo %PATHEXT% veremos su contenido: PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH Es decir, primero intentar localizar un ping.com, si lo encuentra lo ejecuta, si no lo encuentra buscar un ping.exe, si lo encuentra lo ejecuta, etc 2) Hemos hablado de que intentar localizar los anteriores. Pero dnde? 2.1) En primer lugar en el directorio en curso. 2.2) Si no lo localiza, buscar en la variable de entorno %PATH% e ir recorriendo carpeta por carpeta y dentro de cada una de ellas, si no se ha tecleado extensin, en el orden predeterminado de extensiones de la variable %PATHEXT% 2.3) Si al final de esta bsqueda lo encuentra, lo ejecutar. En otro caso nos enviar un mensaje de error como por ejemplo: C:\>micomando micomando no se reconoce como un comando interno o externo, programa o archivo por lotes ejecutable. *** Debemos fijarnos en que bsicamente un comando es algo que puede solicitar datos de entrada, posteriormente hace algo y por ltimo nos da datos de salida. Por ejemplo: copy c:\carpeta\archivo.dat d:\backup El comando (interno) copy, recibe datos, en este caso de la propia lnea de comandos (y en la consola). Esos datos son dos: c:\carpeta\archivo.dat y d:\backup. A continuacin ejecuta la copia. Y por ltimo nos informa de cmo ha ido esa copia. Nos puede dar dos tipos de mensajes: a) O bien nos informa de copia correcta: 1 archivos copiados. b) o puede informarnos de una situacin de error, por ejemplo: El sistema no puede hallar el archivo especificado., o bien: Acceso denegado. 0 archivos copiados. En general los programas o comandos tienen una entrada de datos estndar (STDIN), y una salida de datos cuando ocurre un funcionamiento correcto (STDOUT) y cuando ocurre algn tipo de error (STDERR). Fijmonos que las tres, en los casos de comando de consola, en general, estn redirigidas a la propia consola. Tanto la entrada de datos como los mensajes, sean o no de error, entran y salen por pantalla. Pero el comando o programa, internamente los redirige a salidas o entradas que pueden fsicamente estar redirigidas, o ser redirigidas desde dispositivos que no sean la consola. Tcnicamente, esto se hace a nivel del handle (manejador) del fichero. Algunas veces en la literatura hispana esto se ha mal traducido por controlador. Bsicamente un handle es un simple nmero que referencia internamente en un programa a un fichero. Fijmonos que realmente la entrada de datos es como si estamos leyendo de un fichero y la salida es como si se escribe en un fichero, aunque en el ejemplo que acabamos de ver, estos ficheros son redirigidos a la propia consola.

  • Existen tres nmeros, o handles, que histricamente en informtica han representado siempre lo mismo: el 0 (STDIN), el 1 (STDOUT) y el 2 (STDERR). El resto son libres, a voluntad del programador. Por tanto, y de cara interna a un programa, los datos que recibe de entrada se leen por STDIN, los mensajes de salida se escriben en STDOUT, y los mensajes de error en STDERR y adems se activa un cdigo de error (aunque algunas veces es costoso de distinguir, ya que slo est en la cabeza del programador que lo haya realizado, qu es lo que l considera mensaje informativo y lo que considera mensaje de error pero esto es otra cuestin). Debido a la estandarizacin del STDIN, STDOUT y STDERR (handles 0, 1 y 2) lo que normalmente hace un sistema operativo es redirigir estos a la consola. Este es el comportamiento estndar del sistema, pero nosotros podemos igualmente hacer que sean redirigidos a donde queramos, tal y como veremos posteriormente. Por ejemplo, en el caso del ejemplo anterior del comando copy, podemos hacer: copy c:\carpeta\archivo.dat d:\backup > c:\log.txt El smbolo > est indicando que todo lo que vaya a salir por el STDOUT se escribir, en vez de en la consola, en un archivo de texto c:\log.txt. Repito, porque es importante el matiz: STDOUT a fichero de texto. Es decir, si el comando copy no puede copiar, recordemos que el mensaje de error lo saca en STDERR, por tanto en el fichero de texto no se escribira nada, ya que en el ejemplo anterior, con el smbolo >, slo se ha redirigido el STDOUT. El STDERR queda con los valores predeterminados por el sistema operativo: es decir, se escribe el mensaje de error en consola. *** Hemos comentado que a voluntad del programador de un comando o programa, este puede terminar correctamente o bien establecer un cdigo de error al finalizar (escriba o no adems un mensaje explicativo). El sistema operativo es el encargado de capturar esos cdigos de error y los deja a nuestra disposicin en una variable de entorno llamada %ERRORLEVEL% Podemos, por ejemplo, verificar cual es el comportamiento del comando copy. Para ello vamos a realizar el siguiente ejemplo crendonos una carpeta de trabajo llamada c:\tmp c: cd \ md tmp echo texto de un fichero > c:\tmp\fichero.txt Con esto nos hemos posicionado en c: (por si no lo estuvisemos), hemos ido a su carpeta raz (cd \), y hemos creado una carpeta llamada tmp en donde estuvisemos posicionados en ese momento (md tmp) -md es abreviatura de makedir: crear directorio-. La ltima lnea (echo) nos mostrara por pantalla texto de un fichero, es decir nos lo mostrara en el STDOUT. Pero con el smbolo > lo que hacemos es redirigir el STDOUT (la consola en este caso) a un fichero que en nuestro caso es: c:\tmp\fichero.txt. Si lo abrimos con el cuaderno de notas, veremos realmente el texto anterior. Vamos a copiarlo en otro. Ejecutamos por ejemplo: copy c:\tmp\fichero.txt c:\tmp\copia.txt Si a continuacin de este comando ejecutamos: echo %ERRORLEVEL% veremos que el comando anterior nos informa que ha terminado con 0 (se considera normalmente 0 una finalizacin correcta). Vamos a provocar que el copy termine con error para ver cual es su comportamiento en este caso. Un mtodo muy sencillo seria proteger contra escritura el fichero de salida y luego intentar escribir en l. Es decir: attrib c:\tmp\copia.txt +r (+r es read only -slo lectura-) copy c:\tmp\fichero.txt c:\tmp\copia.txt Vemos que ahora en pantalla nos informa que Acceso denegado. Si a continuacin ejecutamos: echo %ERRORLEVEL% veremos que el cdigo de retorno es 1. NOTA: en general los mensajes de error deben buscarse en la documentacin del programa o

  • comando ya que son a voluntad del programador. El sistema operativo lo nico que hace es situarnos el cdigo de retorno en %ERRORLEVEL% y nosotros podremos tomar acciones en un script de comandos analizando dicha variable de entorno cuando nos interese controlar los cdigos de terminacin. Bien, lo anterior no ha sido ms que un ejemplo para intentar introducir los redirectores del sistema operativo. OPERADORES DE REDIRECCIN > Escribe la salida del comando (normalmente STDOUT) en un fichero o un dispositivo (puede por tanto redirigirse a otro dispositivo, no slo a archivo), en lugar de en la ventana del Smbolo del sistema. < Lee la entrada (STDIN) del comando desde un archivo, en lugar de leerla desde la consola. >> Aade la salida del comando al final de un archivo sin eliminar la informacin que ya est en l. >& Escribe la salida de un controlador en la entrada de otro controlador (lo vemos posteriormente en detalle) & se escribe la salida de un controlador (handle) en otro. Vayamos a un ejemplo prctico. En los ejemplos anteriores hemos visto que la salida de un comando como el copy podemos escribirlo en un fichero con el smbolo >. Pero tambin hemos comentado que slo redirige en STDOUT, por tanto, si el copy enviase un mensaje de error (STDERR) esto no se vera en el fichero. Esto es un problema si lo que queremos es crear un log de ejecucin de un script para poder ver posteriormente la ejecucin: los mensajes de error precisamente los habramos perdido. Pero recordemos que > escribe el STDOUT. Si fusemos capaces de redirigir el STDERR al STDOUT, entonces el > nos escribira todos los mensajes, de funcionamiento correcto o errneo en el fichero. Es decir, si hacemos: copy c:\tmp\fichero.txt c:\tmp\copia.txt >c:\log.txt slo los mensajes de funcionamiento correcto quedaran en c:\log.txt. Pero en cambio si redirigimos la salida de errores: STDERR (handle numero 2) al STDOUT (handle numero 1) y luego escribimos, en ese caso todo quedara reflejado en el archivo log. Por tanto: copy c:\tmp\fichero.txt c:\tmp\copia.txt 2>&1 >c:\log.txt *** Operador de canalizacin (|) o pipe. Este es de los ms interesantes ya que permite pasar toda una salida de datos a un programa que espera toda una entrada de datos en flujo. No todos los programas estn preparados para admitir este tipo de redireccin y debe leerse la documentacin de cada uno de ellos al respecto. Tenemos tres programas del sistema operativo more (ms), find (buscar) y sort (ordenar) que admiten pipes y que nos pueden servir de ejemplo. Veamos. Un dir /s nos muestra todos los archivos desde donde estemos posicionados incluyendo todos los archivos en subcarpetas. Si ejecutamos: dir c:\ /s veremos que empiezan a pasar pantallas de datos que no somos capaces de leer. Podemos redirigir la salida de este comando al more. Realmente el more no es nada ms que un programa que admite como entrada toda la salida de otro comando y que lleva un contador de lneas para irnos mostrando en pantalla 24 lneas y luego esperar a que pulsemos una tecla. Ejecutemos por ejemplo: dir c:\ /s | more (cualquiera de los comandos anteriores puede abortarse con CTRL-C). Un ejemplo de canalizacin y redireccin: imaginemos que queremos en nuestro disco todos los

  • archivos con extensin .log y dejar la informacin en un fichero de salida. dir c:\ /b /s | find /I .log > c:\ficheros_log.txt Los parmetros que he puesto, tanto en el comando dir, como en el comando find, siempre podemos verlos ejecutando dir /? y find /? para buscar los que mejor se adapten a lo que queremos. Otro ejemplo: ver en orden inverso los ficheros de un directorio: dir /b | sort /REVERSE Los filtros (pipes) no slo admiten canalizacin. Tambin pueden usarse, como cualquier programa, con comandos de redireccin para leer entradas y escribir salidas en archivos. Por ejemplo, imaginemos que tenemos un fichero con nombres y queremos ordenarlo alfabticamente. Simplemente: sort < lista.txt > listaalf.txt Esto indicara que la entrada al comando sort viene redirigida desde el fichero lista.txt y que la salida, en vez de dejarla en pantalla, nos la escriba en listaalf.txt. *** Los smbolos de redireccin y canalizacin son potentsimos y a veces, incluso a un programador avezado le pueden causar ms de un problema o costarle su correcta interpretacin. En ejemplos que iremos viendo a lo largo de estos captulos quedar ms claro el concepto. OPERADORES CONDICIONALES Son los operadores && y el operador || Lo que exista despus del operador && se ejecutar slo si la instruccin previa a l -en la misma lnea- ha terminado correctamente (cdigo 0). Por contra, si usamos || slo se ejecutar si la terminacin de la instruccin previa termina incorrectamente (cdigo distinto de cero) Por ejemplo: md kkk && echo finalizado correcta la creacin Slo veremos el mensaje de aviso si la creacin de la carpeta kkk ha sido posible. CONFIGURACIN CMODA DEL INTRPRETE DE COMANDOS Aunque esto no tiene nada que ver con los scripts, podemos fijarnos en que al abrir un intrprete de comandos (cmd.exe) no se pueden realizar funciones de copiar y pegar, lo cual puede sernos incmodo en Windows. La manera de configurar el intrprete de comandos es pinchando con el ratn en la esquina superior izquierda del intrprete de comandos, propiedades, marcamos el casillero de modalidad de edicin rpida. De esta manera, con el botn izquierdo del ratn ya podremos marcar textos. Una vez marcado, pinchamos botn derecho del ratn y esto nos lo enva al portapapeles (es decir, esta es la accin copiar a la que estamos acostumbrados. La accin pegar, es simplemente botn derecho (sin haber marcado nada previamente). Lo que tengamos en el portapapeles (lo hayamos llevado mediante la accin anterior, o bien lo hayamos copiado desde cualquier otra ventana Windows) lo pegar en donde est el cursor. CONCEPTOS EN UN SCRIPT CONTROL DE FLUJOS Acabamos de ver unos conceptos sobre entorno, comandos, variables, etc., que son bsicos para poder realizar un script, pero hasta el momento no hemos visto ninguna instruccin excepto las puestas en los ejemplos previos, ni tampoco hemos visto cmo el shell ejecuta el script y cmo se puede tener control sobre la ejecucin. Bsicamente un script de comandos, tal y como hemos comentado, no es nada ms que escribir en un archivo de texto con extensin .bat o .cmd todas las instrucciones que iramos haciendo manualmente. Adems, dentro del propio script, en funcin de resultados que vayamos obteniendo se pueden tomar acciones. Recordemos algunas de las instrucciones vistas hasta el momento:

  • Instruccin: ECHO, su objetivo es mostrar por el STDOUT (normalmente la consola) el literal que exista a continuacin. Recordemos que lo primero que hace el intrprete de comandos es expandir las instrucciones, es decir, si existe una variable de entorno (delimitada por smbolos %), lo primero que hace es sustituir dicha variable por su contenido. Es decir, si escribimos en un script: echo esto es %var% prueba y la variable de entorno var contiene el literal una, el intrprete de comandos: 1) Realiza la sustitucin de las variables de entorno, por tanto la lnea quedara como: ECHO esto es una prueba 2) A continuacin, ejecuta la instruccin: Como ECHO es un comando interno que escribe en el STDOUT lo que hay a continuacin, nos mostrar el literal esto es una prueba. Es importante la matizacin anterior ya que la expansin de variables es el primer paso y lo es para todas las instrucciones. Si hubisemos cometido un error y hubisemos puesto: ECHA esto es %var% prueba 1) Expandira la instruccin como: ECHA esta es una prueba 2) Intentara ejecutar la instruccin. ECHA no es el nombre de un comando interno, por tanto buscara en la carpeta en curso y posteriormente en el PATH un programa (otro script, o un .com, o un .exe, etc de acuerdo a las reglas vistas anteriormente). Si lo encuentra ejecutar el programa o script ECHA y si no lo encuentra nos dir que sucede un error. NOTA: La sintaxis completa de ECHO es: ECHO literal a escribir ECHO. (un . pegado a la instruccin sin separacin: escribe una lnea en blanco) ECHO ON ECHO OFF Estas dos ltimas son instrucciones a ejecutar slo dentro de un script. Veamos su uso. Nos creamos un script llamado por ejemplo: pr.cmd en mi usuario y en una nueva carpeta de pruebas llamada tmp con el contenido: set var=Hola echo %var% mundo. set var= Lo guardamos en disco y ahora lo ejecutamos. Qu vemos?: C:\Documents and Settings\miusuario\tmp>set var=Hola C:\Documents and Settings\miusuario\tmp>echo Hola mundo Hola mundo C:\Documents and Settings\miusuario\tmp>set var= Es decir, nos ha ido mostrando todas las lneas que va ejecutando y mezclado con las salidas que a su vez va dando el script. Si queremos suprimir la salida de las lneas y dejar solamente la salida de los comandos, es decir Hola mundo, lo primero que debemos decirle al script es que no queremos ECO de lo que va traduciendo. Este ECO es til cuando estamos depurando y probando un script, pero, cuando lo tenemos finalizado y correcto, lo lgico es ver slo la salida y no lnea por lnea. En este caso podemos poner como primera lnea del script: @ECHO OFF El smbolo @ como primer carcter en una lnea del script indica que no queremos que esa lnea se vea en la ejecucin. Si adems le damos la orden ECHO OFF, le estamos diciendo que hasta el final del script, o bien hasta que se encuentre otra orden ECHO ON, no muestre nada de la ejecucin (s de la salida de instrucciones) por pantalla. Es decir, en nuestro caso, si no queremos ver nada ms que el literal Hola mundo, nos quedan

  • dos posibilidades: 1) Poner una @ al comienzo de cada instruccin en el script. O bien: 2) Poner como primera lnea del script @ECHO OFF Vamos a hacer un parntesis en este captulo e introducir el concepto de nombre lgico de dispositivo. NOMBRES LGICOS DE DISPOSITIVOS Hay ciertos dispositivos que podemos usar en cualquier comando o dentro de un script con nombres reservados que se refieren a dispositivos, normalmente lgicos, de nuestra mquina. Por ejemplo: CON se refiere a la consola. Lo que se enve o reciba desde la consola se puede referenciar con CON. LPT1 se refiere a la impresora. Lo que se enve a l se escribir en la impresora (si est asignada a ese puerto). NUL dispositivo nulo. Lo que se enve a l, se pierde. Aunque existen ms dispositivos lgicos, llegado este punto slo vamos a ver estos tres. Veamos unos ejemplos: 1) Imaginemos que hemos recibido una clave de registro de un producto por mail, y lo queremos guardar en un fichero llamado licencia.txt en una carpeta determinada. La manera clsica de hacerlo mediante Windows es abrir el cuaderno de notas, copiar la clave desde el mail recibido y guardar el fichero en la carpeta que queremos con el nombre licencia.txt. Bien, podramos hacer en una consola de comandos: copy con licencia.txt En este punto se quedar el cursor esperando una entrada. Tecleamos la clave recibida (o la copiamos desde el mail), y para finalizar la entrada de datos le damos a CTRL-Z (CTRL-Z es la marca estndar de fin de fichero). Es decir, hemos copiado desde la consola a un fichero de la misma forma que si hubisemos copiado un fichero a otro fichero. 2) Queremos enviar un fichero a impresora: copy fichero.txt lpt1 3) No queremos ver, por ejemplo despus de un comando copy la lnea de xx archivos copiados que siempre nos informa el copy. Simplemente redirigimos la salida al dispositivo nulo. copy fichero1.txt fichero2.txt >nul RETOMANDO EL CONTROL DE FLUJOS DE EJECUCIN Una vez hecho el parntesis anterior, vamos a ver las instrucciones de control flujo. Bsicamente son 3. 1) Instruccin GOTO (ir a) Permite en un punto determinado de nuestro script saltar a otro punto del script. Normalmente se usa despus de una pregunta lgica por algn resultado (por ejemplo, dentro de una instruccin IF). GOTO nombre_etiqueta Y en algn lugar de nuestro script debemos tener :nombre_etiqueta (ntense los :) En este caso, al ejecutar la instruccin GOTO, buscar en el script la lnea :nombre_etiqueta y bifurcar a dicha lnea. NOTA: Existe una etiqueta implcita en cualquier script que no es necesario definir, :EOF (End Of File Fin de fichero). Por tanto, la ejecucin de la instruccin GOTO :EOF implica que se saltar hasta el final del fichero y por tanto finalizar el script. 2) Instruccin IF (si). Recordemos que lo encerrado entre corchetes es opcional if [not] errorlevel nmero comando [else expresin] Estamos verificando si la variable %ERRORLEVEL%, que indica el cdigo de retorno de un comando anterior, tiene un valor determinado. Si lo tiene ejecutar el comando y si no lo

  • tuviese y hemos codificado en la lnea (es opcional) un ELSE (en otro caso), ejecutar precisamente ese ELSE. if [not] cadena1==cadena2 comando [else expresin] cadena1 y cadena2 pueden ser cualquier cosa incluidas variables de entorno. Recordemos que lo primero que se hace es la expansin de variables. Hay que tener muchsimo cuidado con esto y no me gustan las instrucciones del estilo anterior a menos que tengamos delimitadores especficos. Voy a intentar explicarlo. Imaginemos que tenemos una variable var1 con contenido 1 y otra var2 con contenido tambin 1. La instruccin: if %var1%==%var2% echo valen lo mismo Se ejecutar sin problemas y nos sacar el mensaje valen lo mismo. Si var2 contiene un 2, la instruccin anterior, al no ser iguales, no mostrar nada. Pero y si var1 contiene Hola mundo, que sucedera? Pues un desastre. Al expandir la expresin quedara: if Hola mundo==2 echo valen lo mismo Detrs del hola no hay smbolo de comparacin, por lo cual la instruccin es sintcticamente incorrecta. Lo mismo pasara si var1 o var2 no tienen contenido. En estos casos, el truco consiste en encerrarlas entre algn delimitador. Por ejemplo, comillas -ya que estas definen un literal. Es decir: if %var1%==%var2% echo valen lo mismo Esto al expandirse quedara: if hola mundo==2 echo valen lo mismo La comparacin se realiza entre literales entrecomillados lo cual no provoca error ni aun en el caso de que alguno sea nulo al no tener contenido. if [not] exist nombreDeArchivo comando [else expresin] if [/i] cadena1 operadorDeComparacin cadena2 comando [else expresin] El /i realiza la comparacin de tal manera que no se distingue entre maysculas y minsculas. Es decir HOLA es lo mismo que hOLa. Fijmonos que hemos puesto no un == (igualdad) en este caos, sino que por primera vez se ha puesto operadorDeComparacion. Este operador que veremos a continuacin, y el smbolo == no es nada ms que uno de ellos. if defined variable comando [else expresin] OPERADORES DE COMPARACIN Especifica un operador de comparacin de tres letras. En la siguiente tabla puede ver los valores de operadorDeComparacin. EQU igual a (es lo mismo que ==) NEQ no es igual a LSS menor que LEQ menor que o igual a GTR mayor que GEQ mayor que o igual a PARMETROS Cualquier script es capaz de recibir parmetros desde la lnea invocante. Se considera parmetro cualquier literal enviado en la lnea que invoca al script. El sistema considera que los parmetros estn separados por espacios en blanco o bien por el delimitador ;. Cada parmetro se referencia dentro del script por %1, %2, %3, etc Vamos a crear un script que reciba dos parmetros, el nombre de un fichero y el nombre de una carpeta. El objetivo del script es copiar el archivo desde la carpeta en donde estemos posicionados en la carpeta destino, siempre y cuando no exista ya en el destino. Una manera grosera de realizar el script, llammosle copia.cmd, sin verificar que los parmetros son correctos, sera:

  • @echo off if not exist %2\%1 copy %2 %1 Si invocsemos al script de la siguiente manera: copia.cmd mifichero.txt c:\backup al desarrollar la instruccin el script, realizara: if not exist c:\backup\mifichero.txt copy mifichero.txt c:\backup lo cual es precisamente lo que queramos hacer. He comentado que este script, tal y como est, est realizado de una manera grosera. Si el nombre del archivo o el nombre de la carpeta destino tuviese espacios en blanco el sistema considerara que dicho espacio en blanco es un delimitador de parmetros y por tanto nos llegaran al script ms parmetros de los deseados. Realmente para realizar correctamente el script deberamos hacer: @echo off if {%1}=={} goto error if {%2}=={} goto error if {%3} NEQ {} goto error if not exist %1 goto error1 if not exist %2\nul goto error2 if exist %2\%1 goto aviso copy %1 %2\%1 2>&1 >nul if not errorlevel 1 goto correcto echo Copia errnea. Verifique permisos de la carpeta destino. goto:EOF :error echo parmetros errneos. Deben recibirse dos parmetros. goto :EOF :error1 echo Nombre del fichero origen no existe. goto :EOF :error2 echo Carpeta destino no existe. goto :EOF :aviso: echo El archivo ya existe en el destino. No se ha realizado copia. goto :EOF :correcto echo Archivo copiado correctamente. goto :EOF Y la manera de invocar al comando sera: copia.cmd nombre fichero.xxx c:\carpeta destino Ntese que hemos entrecomillado cada uno de los parmetros. De esta manera slo se recibirn dos parmetros ya que si no, se recibiran 4 al usar como delimitador el sistema los espacios en blanco entre ellos. Comentemos un poco el script. * Verificamos que hemos recibido 2 parmetros y slo 2. * Verificamos que exista el fichero origen * Verificamos que exista la carpeta destino. Para verificarlo usamos un pequeo truco: preguntar por el dispositivo nul en la carpeta destino. Si no existe, es que la carpeta no existe. * Verificamos que de acuerdo a las especificaciones del script no exista ya el fichero en la carpeta destino. * Realizamos la copia. Redirigimos todo a nul para que no de mensajes de archivos copiados.

  • * Comprobamos el cdigo de retorno y si no es cero enviamos el mensaje correspondiente. * Damos un mensaje de copia correcta cuando se ha finalizado correctamente el script. Bien, el ejemplo anterior nos puede servir para la introduccin de lo que son los parmetros y cmo se deben usar o referenciar en el script. Vamos a ver toda la casustica ms en detalle. Realmente podemos referenciar los parmetros desde %0 a %9. El parmetro recibido en %0 no se teclea y siempre el sistema nos pasa como contenido el nombre del script invocado. Hagamos una prueba: @echo off echo Parmetro 0: %0 %1 a %9 son los posibles parmetros enviados en la lnea de comandos. Realmente pueden pasarse ms de 9 parmetros pero slo 9 de ellos sern accesibles directamente. Si passemos ms, hay que usar el comando shift, el cual tiene por objeto desplazar los parmetros. Es decir, al ejecutar shift lo que se hace es que el %2 pasa a ser %1 (el %1 se pierde por lo que debemos guardarlo), el %3 pasa a ser el %2, etc De tal manera que al final el %9 pasa a contener el posible dcimo parmetro pasado. Realicemos como prueba: @echo off echo Antes de desplazar echo P